【问题标题】:Can constructing an empty std::optional<T> call T's default constructor?构造一个空的 std::optional<T> 可以调用 T 的默认构造函数吗?
【发布时间】:2021-01-05 13:37:48
【问题描述】:

存储在std::optional&lt;T&gt; 实例中的对象是否保证在放置new 时就地初始化?这是我对大多数实现的期望,但是,我也可以想象以下实现:

/* pseudocode */
template<typename T> class optional {
    T object;
    bool has_value;
};

在这种情况下,当构造一个不包含值的std::optional&lt;T&gt; 时,必须调用T 的默认构造函数。
是不是保证不是这样,即使T确实有默认构造函数,也不会被调用

我能在 cppreference 上找到与内存管理相关的所有内容如下:“如果一个可选项包含一个值,则该值保证作为可选对象占用空间的一部分进行分配,即不会进行动态内存分配地点。” (https://en.cppreference.com/w/cpp/utility/optional)
但是,我上面的“实现”也符合这个要求。

【问题讨论】:

  • 您链接的文档指出T 的唯一要求是dectructible,所以我假设是这样。除非使用placement new,否则这是不可能的。
  • 它在任何时候都不是用 new 构造的。默认情况下它不构造对象。实现通常只是在类中保留额外的空间以供将来可能的构建。
  • @ALX23z 问题指定了新的位置,这也是这种初始化在幕后工作的方式。否则,您将如何在您提到的在类中保留的额外空间中构造一个对象?
  • @super 哦...错过了“放置”部分。我也相信它可以通过联合来完成,而不需要放置新的。
  • @ALX23z 可能用于聚合,但如果您在联合中使用具有用户定义的构造函数和析构函数的类,您通常也需要使用placement new 在活动成员之间切换。所以最后你不会有太多收获。

标签: c++ c++17 language-lawyer std c++20


【解决方案1】:

标准要求std::optional&lt;T&gt; 由其默认构造函数或std::nullopt_t 构造函数初始化,不会初始化其包含的T 对象。

来自[optional.ctor](强调我的):

constexpr optional() noexcept;
constexpr optional(nullopt_t) noexcept;
后置条件: *this 不包含值。
备注: 没有初始化任何包含的值。 对于每个对象类型T,这些构造函数都是 constexpr 构造函数([dcl.constexpr])。

【讨论】:

    猜你喜欢
    • 2018-10-04
    • 1970-01-01
    • 2017-05-07
    • 1970-01-01
    • 1970-01-01
    • 2018-02-10
    • 1970-01-01
    • 2023-03-15
    相关资源
    最近更新 更多