std::optional如何延迟初始化? / std::optional 是如何实现的?
How does std::optional delay initialization? / How is std::optional implemented?
最近我对初始化很感兴趣。我特别感兴趣的一件事是 std::optional,因为它能够在类型实例被声明后对其进行初始化。我已经尝试阅读可选 header 中的代码,但代码太 'bombastic' 我无法理解。
std::optional 如何延迟堆栈上 object 的初始化?我假设它只是在堆栈上保留 sizeof( 的初始化。但是它具体是怎么做到的呢?它是如何实施的?我该如何自己实施?
编辑:澄清一下,我知道 std::optional 基本上有一个 bool 成员来跟踪 object 是否初始化,另一个成员包含数据。
然而,我不明白的是 optional 是如何能够手动初始化某些东西的。
它是如何破坏一个object的?旧的被破坏后又如何重建新的?
表示 std::optional<T>
的“明显”方式是使用指示值是否与包含 T
的 union
一起设置,即,如下所示:
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";
}
}
最近我对初始化很感兴趣。我特别感兴趣的一件事是 std::optional,因为它能够在类型实例被声明后对其进行初始化。我已经尝试阅读可选 header 中的代码,但代码太 'bombastic' 我无法理解。
std::optional 如何延迟堆栈上 object 的初始化?我假设它只是在堆栈上保留 sizeof(
编辑:澄清一下,我知道 std::optional 基本上有一个 bool 成员来跟踪 object 是否初始化,另一个成员包含数据。
然而,我不明白的是 optional 是如何能够手动初始化某些东西的。
它是如何破坏一个object的?旧的被破坏后又如何重建新的?
表示 std::optional<T>
的“明显”方式是使用指示值是否与包含 T
的 union
一起设置,即,如下所示:
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";
}
}