c++ - 为什么 c++17 的 emplace() 函数没有引用资格?

标签 c++ language-lawyer c++17

C++17 引入了一些新的函数签名 emplace_back()类型函数(std::optional<> 也有一个),但它们不是引用限定的。这允许 emplace_back()在临时对象上调用并绑定(bind)到左值引用,即使对象的生命周期没有延长。请考虑以下事项:

#include <vector>
#include <optional>
#include <iostream>

struct A {
   A(int i) : i(i) { std::cout << "constructor called: " << i << '\n'; }
   ~A() { std::cout << "destructor called\n"; }

   int i;
};

int main() {
    auto & a = std::optional<A>().emplace(5);
    std::cout << "a: " << a.i << '\n';
    auto & v = std::vector<A>().emplace_back(5);
    std::cout << "v: " << v.i << '\n';

    // This fails to compile, because value() *is*
    // ref-qualified so it cannot bind to an lvalue reference
    //auto & a2 = std::optional<A>(std::in_place, 5).value();

    auto const & a2 = std::optional<A>(std::in_place, 5).value();
    std::cout << "a2: " << a2.i << '\n';
}

输出:

constructor called: 5
destructor called
a: 5
constructor called: 5
destructor called
v: 0
constructor called: 5
destructor called
a2: 5

我找不到与此相关的任何现有错误或问题,但也许我只是遗漏了一些东西。在std::optional<>::value()的情况下,它大部分都有效,但仍然允许绑定(bind)到 const 左值引用,同时不能适本地延长包含类型的生命周期。

这些函数没有引用限定的原因是什么,为什么 std::optional<>::value()在右值上使用时不能正确延长包含对象的生命周期?

最佳答案

std 库中几乎没有任何东西是引用限定的。

至于value,它返回一个右值引用。当您有一个右值限定方法返回对内部状态的引用时,您有两种选择。

您可以返回一个值,也可以返回一个右值引用。

如果您返回一个值,这意味着右值可选上的 .value() 会移动,而左值可选上的 .value() 不会。这可能令人惊讶。

.value() 返回右值的代价是引用生命周期延长不适用。 .value() 返回右值拷贝的代价是移动的代价,加上它表现不同的惊喜。

两者都有缺点。我记得它是可选设计中的一个讨论点。如果我的内存是正确的,那就意味着这个决定是睁着眼睛做出的。

除非对引用生命周期延长进行极端改进,否则将右值返回到内部状态的右值函数将始终绑定(bind)到 const& 而不会延长外部对象的生命周期。

我的经验中真正的痛点是for(:)循环;

std::optional<std::vector<int>> try_get_vec();

for (int x : try_get_vec().value()) // I know the optional won't be empty

上面有一个悬空引用。

关于c++ - 为什么 c++17 的 emplace() 函数没有引用资格?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54116810/

相关文章:

c - 6.3.1.1p2 的含义,要点 2

c++ - switch 语句条件下同时具有模板和非模板转换运算符的类

c++ - enable_if_t 中包含折叠表达式的编译器错误

c++ - 错误: reference to overloaded function could not be resolved

c++ - Qt/Qt Creator - 程序意外结束。 <程序路径> 崩溃

c++ - *(&arr + 1) - arr 如何给出数组大小

c++ - 为什么不允许指针+指针,但允许指针+整数?

c++ - 寻找部分代码的解释

c - C标准是否指定递增指针时进位传播的距离?

c++ - 拆分 C++ TypeList 的最优雅方式