3 回答
TA贡献1829条经验 获得超6个赞
这个漏洞是否在语言规范中有其他一些条款?
是的,见12.8§34和§35:
当满足某些条件时,允许实现省略类对象的复制/移动构造[...]复制/移动操作的省略,称为复制省略,允许在...中的返回语句中。具有类返回类型的函数,当表达式是非易失性自动对象的名称时,具有与函数返回类型相同的cv-nonqualified类型[...]
当满足复制操作的省略标准并且要通过左值指定要复制的对象时,首先执行用于选择复制的构造函数的重载决策,就好像该对象由右值指定一样。
只是想再增加一点,按值返回应该是默认选择,因为在最坏的情况下,返回语句中的命名值,即C ++ 11,C ++ 14和C ++ 17中没有elisions的处理作为一个左值。因此,例如,以下函数使用-fno-elide-constructors
标志进行编译
std::unique_ptr<int> get_unique() { auto ptr = std::unique_ptr<int>{new int{2}}; // <- 1 return ptr; // <- 2, moved into the to be returned unique_ptr}...auto int_uptr = get_unique(); // <- 3
在编译时设置标志,在此函数中发生两个移动(1和2),然后稍后移动(3)。
TA贡献1804条经验 获得超3个赞
这绝不具体std::unique_ptr
,但适用于任何可移动的类。由于您按价值返回,因此语言规则保证了这一点。编译器尝试删除副本,如果无法删除副本则调用移动构造函数,如果无法移动则调用复制构造函数,如果无法复制则无法编译。
如果你有一个接受std::unique_ptr
作为参数的函数,你将无法将p传递给它。您必须显式调用move构造函数,但在这种情况下,您不应在调用后使用变量p bar()
。
void bar(std::unique_ptr<int> p){ // ...}int main(){ unique_ptr<int> p = foo(); bar(p); // error, can't implicitly invoke move constructor on lvalue bar(std::move(p)); // OK but don't use p afterwards return 0;}
TA贡献1794条经验 获得超8个赞
unique_ptr没有传统的复制构造函数。相反,它有一个使用右值引用的“移动构造函数”:
unique_ptr::unique_ptr(unique_ptr && src);
右值参考(双&符号)仅绑定到右值。这就是当您尝试将左值unique_ptr传递给函数时出现错误的原因。另一方面,从函数返回的值被视为右值,因此自动调用移动构造函数。
顺便说一句,这将正常工作:
bar(unique_ptr<int>(new int(44));
这里的临时unique_ptr是一个右值。
- 3 回答
- 0 关注
- 1716 浏览
添加回答
举报