Joh*_*ard 5 c++ language-lawyer c++17
C++ 17为一些emplace_back()类型的函数引入了一个新的函数签名(std::optional<>也有一个),但它们不是ref-qualified.这允许emplace_back()在临时和绑定到左值引用上调用,即使未扩展对象的生命周期.考虑以下:
#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';
}
Run Code Online (Sandbox Code Playgroud)
输出:
constructor called: 5
destructor called
a: 5
constructor called: 5
destructor called
v: 0
constructor called: 5
destructor called
a2: 5
Run Code Online (Sandbox Code Playgroud)
我找不到任何与此相关的错误或问题,但也许我只是遗漏了一些东西.在这种情况下std::optional<>::value(),它主要起作用,但仍允许绑定到const lvalue引用,同时不能正确扩展包含类型的生命周期.
是否有任何理由为什么这些函数不被重新限定,为什么std::optional<>::value()在rvalue上使用时没有正确延长所包含对象的生命周期?
std 库中几乎没有任何内容是 ref 限定的。
至于value,它返回一个右值引用。当您有一个右值限定方法返回对内部状态的引用时,您有两种选择。
您可以返回一个值,也可以返回一个右值引用。
如果返回一个值,这意味着.value()在右值可选上执行移动,而.value()在左值可选上则不会。这可能会令人惊讶。
返回右值的代价.value()是引用生命周期扩展不适用。.value()返回右值副本的成本就是移动的成本,加上它的行为不同所带来的惊喜。
两者都有缺点。我记得它是可选设计中的一个讨论点。如果我没记错的话,那就说明这个决定是经过深思熟虑做出的。
除非对引用生命周期扩展进行极大的改进,否则将右值返回到内部状态的右值上的函数始终会绑定到外部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
Run Code Online (Sandbox Code Playgroud)
上面有一个悬空引用。