unique_ptr
不允许复制构造,而是支持移动语义.然而,我可以从函数返回一个 unique_ptr
并将返回的值分配给一个变量.
unique_ptr<T>
does not allow copy construction, instead it supports move semantics. Yet, I can return a unique_ptr<T>
from a function and assign the returned value to a variable.
#include <iostream>
#include <memory>
using namespace std;
unique_ptr<int> foo()
{
unique_ptr<int> p( new int(10) );
return p; // 1
//return move( p ); // 2
}
int main()
{
unique_ptr<int> p = foo();
cout << *p << endl;
return 0;
}
上面的代码编译并按预期工作.那么如何行 1
不调用复制构造函数并导致编译器错误?如果我不得不改用 2
行,那是有意义的(使用 2
行也可以,但我们不需要这样做).
The code above compiles and works as intended. So how is it that line 1
doesn't invoke the copy constructor and result in compiler errors? If I had to use line 2
instead it'd make sense (using line 2
works as well, but we're not required to do so).
我知道 C++0x 允许 unique_ptr
出现这个异常,因为返回值是一个临时对象,一旦函数退出就会被销毁,从而保证返回指针的唯一性.我很好奇这是如何实现的,它是编译器中的特殊情况,还是语言规范中是否有其他条款可以利用?
I know C++0x allows this exception to unique_ptr
since the return value is a temporary object that will be destroyed as soon as the function exits, thus guaranteeing the uniqueness of the returned pointer. I'm curious about how this is implemented, is it special cased in the compiler or is there some other clause in the language specification that this exploits?
语言规范中是否有其他条款可以利用?
is there some other clause in the language specification that this exploits?
是的,请参阅 12.8 §34 和 §35:
Yes, see 12.8 §34 and §35:
当满足某些条件时,允许实现省略类对象的复制/移动构造 [...]这种复制/移动操作的省略,称为复制省略,被允许 [...]在具有类返回类型的函数中的 return 语句中,当表达式是非易失性自动对象与函数返回类型 [...]
When certain criteria are met, an implementation is allowed to omit the copy/move construction of a class object [...] This elision of copy/move operations, called copy elision, is permitted [...] in a return statement in a function with a class return type, when the expression is the name of a non-volatile automatic object with the same cv-unqualified type as the function return type [...]
当满足省略复制操作的条件并且要复制的对象由左值指定时,为副本选择构造函数的重载决议首先执行就好像对象由右值指定一样.
When the criteria for elision of a copy operation are met and the object to be copied is designated by an lvalue, overload resolution to select the constructor for the copy is first performed as if the object were designated by an rvalue.
<小时>
只是想再补充一点,按值返回应该是这里的默认选择,因为在最坏的情况下,返回语句中的命名值,即在 C++11、C++14 和 C++ 中没有省略17 被视为右值.例如,以下函数使用 -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) 中进行了一次移动.
With the flag set on compilation there are two moves (1 and 2) happening in this function and then one move later on (3).
这篇关于从函数返回 unique_ptr的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持html5模板网!