此頁面是Microsoft特定的。確實,標準允許在函數返回期間對複製構造函數執行兩次,一次或零次調用(這稱爲複製elision)。事實上,一個電話總是足夠的。
假設你寫:
A f(int x) {
return A(x);
}
void g() {
A r = f(10);
}
的方式實現MSVC這就是:
void f_impl(A* r, int x) {
new((void*)r) A(x); // construct the return value into r
}
void g_impl() {
A r = __uninitialized__;
f_impl(&r, 10);
}
這裏你可以看到零調用拷貝構造函數,沒有臨時對象。
如果調用f
這樣的:
void g() {
f(10);
}
那麼編譯器仍然需要地方建設的返回值,因此它會創建一個臨時的:
void g_impl() {
A r = __uninitialized__;
f_impl(&r, 10);
r.~A(); // destruct temporary
}
當調用拷貝構造函數?在執行f
的時候,無法知道哪個f
的本地將被退回。例如。這樣的:
A f(int x)
{
A r1;
A r2;
// ...do something complicated modifying both r1 and r2...
if(x)
return r1;
// ...do something complicated...
return r2;
}
被翻譯成這樣的事情:
void f_impl(A* r, int x)
{
A r1;
A r2;
// ...do something complicated modifying both r1 and r2...
if(x)
{
new((void*)r) A(r1); // copy construct r1
return;
}
// ...do something complicated...
new((void*)r) A(r2); // copy construct r2
}
如果一個函數返回一個引用,那是否也被認爲是臨時的? – 2012-01-27 05:45:32
@SethCarnegie:不,因爲引用不是對象(儘管我不能想到這可能很重要的情況)。 – Mankarse 2012-01-27 07:43:47
當您嘗試將臨時對象綁定到從函數返回的引用時,它會發生排序。 (不要這樣做!)。 – MSalters 2012-01-27 08:42:41