1

最近我对初始化感兴趣。我特别感兴趣的一件事是 std::optional ,因为它能够在声明类型的实例后对其进行初始化。我已经尝试阅读可选标题中的代码,但代码太“夸张”了,我无法理解。

std::optional 如何能够延迟堆栈上对象的初始化?我假设它只是在堆栈上保留 sizeof(<whichever_type) 字节数,然后重新解释这些字节以用于 <whichever_bytes> 的初始化。但它具体是如何做到的呢?它是如何实施的?我怎样才能自己实现呢?

编辑:澄清一下,我知道 std::optional 基本上有一个 bool 成员来跟踪对象是否已初始化,以及另一个包含数据的成员。

但是,我不明白 optional 是如何手动初始化某些东西的。

它是如何破坏对象的?旧的被破坏后,它如何能够重新构建新的?

4

1 回答 1

3

表示 an 的“明显”方式std::optional<T>是使用指示值是否与union包含 a 的 a一起设置T,即,如下所示:

template <typename T>
class optional {
    bool isSet = false;
    union { T value; };
public:
    // ...
};

默认情况下, 中的成员union未初始化。相反,您需要使用放置new和手动销毁来管理union. 从概念上讲,这类似于使用字节数组,但编译器会处理任何对齐要求。

这是一个显示一些操作的程序:

#include <iostream>
#include <memory>
#include <string>
#include <utility>
#include <cassert>

template <typename T>
class optional {
    bool isSet = false;
    union { T value; };
    void destroy() { if (this->isSet) { this->isSet = true; this->value.~T(); } }

public:
    optional() {}
    ~optional() { this->destroy(); }
    optional& operator=(T&& v) {
        this->destroy();
        new(&this->value) T(std::move(v));
        this->isSet = true;
        return *this;
    }   

    explicit operator bool() const { return this->isSet; }
    T&       operator*()       { assert(this->isSet); return this->value; }
    T const& operator*() const { assert(this->isSet); return this->value; }
};  

int main()
{   
    optional<std::string> o, p;
    o = "hello";
    if (o) {
        std::cout << "optional='" << *o << "'\n";
    }   
}   
于 2020-12-24T18:24:17.107 回答