就地构造(placement new)与移动构造(std::move)

1.就地构造通常与 union 关键字一并使用,因为union会进行延迟构造并且预先开辟空的内存空间,因此这样的组合任务是较佳实现。

例子:

class FixedValueMessage {

    /* 定值数据 */
public:

    explicit FixedValueMessage(const EthernetDataFrame &ethernetDataFrame) : ethernetDataFrame({ethernetDataFrame}) {

        if (ethernetDataFrame.getAPPIDType() != APPIDType::Type::fixedValue_send) {
            throw std::runtime_error(
                    "Constructor illegally, EthernetDataFrame type is " + ethernetDataFrame.getAPPIDTypeString() + ".");
        }

        auto data = ethernetDataFrame.getAPDU();

        if (data.empty()) {
            throw std::runtime_error("Constructor illegally, EthernetDataFrame data is empty.");
        }

        /* 分别构造8个通道的 零漂值 和 线性值 */
        ptrdiff_t offset = 0l;

        new(&channel1) Channel{data.cbegin(), data.cbegin() + Channel::getSizeInBytes()};

        offset += Channel::getSizeInBytes();

        new(&channel2) Channel{data.cbegin() + offset, data.cbegin() + offset + Channel::getSizeInBytes()};

        offset += Channel::getSizeInBytes();

        new(&channel3) Channel{data.cbegin() + offset, data.cbegin() + offset + Channel::getSizeInBytes()};

        offset += Channel::getSizeInBytes();

        new(&channel4) Channel{data.cbegin() + offset, data.cbegin() + offset + Channel::getSizeInBytes()};

        offset += Channel::getSizeInBytes();

        new(&channel5) Channel{data.cbegin() + offset, data.cbegin() + offset + Channel::getSizeInBytes()};

        offset += Channel::getSizeInBytes();

        new(&channel6) Channel{data.cbegin() + offset, data.cbegin() + offset + Channel::getSizeInBytes()};

        offset += Channel::getSizeInBytes();

        new(&channel7) Channel{data.cbegin() + offset, data.cbegin() + offset + Channel::getSizeInBytes()};

        offset += Channel::getSizeInBytes();

        new(&channel8) Channel{data.cbegin() + offset, data.cbegin() + offset + Channel::getSizeInBytes()};

        offset += Channel::getSizeInBytes();

        /* 拷贝采样频率 */
        std::copy(data.cbegin() + offset, data.cbegin() + offset + ARR_SIZE(samplingFrequency), samplingFrequency);
    }

    ~FixedValueMessage() = default;

    friend class EthernetDataFrame;

private:

    union {
        Channel channel1;               /* 通道1 */
    };

    uint8_t samplingFrequency[2]{};           /* 采样频率 */

    EthernetDataFrame ethernetDataFrame;       /* 原始帧 */
};

2. std::move通常应当在尚未申请空间时使用,本质是一种资源所有权的转移,从而避免申请空间的昂贵开销。

 

posted @ 2025-02-08 13:22  BlackSnow  阅读(39)  评论(0)    收藏  举报