簡體   English   中英

按值返回是否調用復制構造函數或復制賦值運算符?

[英]Does a return by value call the copy constructor or the copy assignment operator?

假設編譯器中沒有返回值優化。
在c ++中,當對象按函數返回值時,真正的步驟如下,我是否正確? 總共,第三次調用構造函數。

本地 (普通構造函數)-> 臨時 (副本構造函數)---> 外部 (副本構造函數或副本Assignemt運算符)

  1. 創建一個本地對象,在這里它調用普通的構造函數;
  2. 使用本地對象創建了一個臨時對象,在這里它調用了復制構造函數;
  3. 將臨時對象分配給外部的實際對象(a),在這里它調用復制構造函數(case1)或復制賦值運算符(case2)
class Name{...};

Name func(){
    // ...
    Name local;
    return local;
}

情況1:

Name outside  = func(); // call copy constructor?

情況2:

Name outside;
outside = func(); // call copy assignment operator?

如果我在第一部分中是正確的,那么如果啟用了返回值優化怎么辦?

這個問題讓我思考,因此從這個意義上講,這是一個好問題。 我在Visual Studio C ++ Express 2010上的“調試”模式下運行了以下測試代碼。

#include <iostream>

using namespace std;

class Foo
{
public:
    Foo(int arg) { val = arg; cout<<"Constructor (normal): "<<val<<endl; }
    Foo(const Foo& ref) { val = ref.val; cout<<"Copy constructor: "<<val<<endl; }
    const Foo& operator=(const Foo& rval)
    {
        cout<<"Assignment operator from object "<<rval.val<<" to object "<<val<<endl;
        val = rval.val; 
        return *this;
    }


    int val;
};

Foo process() {Foo t(2); return t; }

int main()
{
    Foo a(1);
    a = process();

    system("pause");
    return 0;
}

結果:

Constructor (normal): 1
    Constructor (normal): 2
    Copy constructor: 2
    Assignment operator from object 2 to object 1
    Press any key to continue . . .

因此,案例2似乎是正確的。 構造外部“ Foo”之后,將在函數內部構造“ Foo”對象。 然后,使用復制構造函數創建另一個對象,最后調用賦值運算符將結果復制到對象a。

返回值的優化將取決於編譯器和設置。 例如,當我在發布模式下構建和運行時,沒有調用復制構造函數,這表明該臨時對象僅用於調試模式。 (我不是這個主題的專家。)

C ++中的復制省略/返回值優化允許它跳過調用復制構造函數。

情況1,您在返回中使用副本構造並構建“外部”實例。 這些都可以被忽略。 C ++允許ellide即使他們有可衡量的副作用,這些函數調用-無作為,如果規則適用。

情況2,您正在使用賦值運算符將您的值添加到變量“外部”中,“按原樣復制”省略例外不適用於此處。 因此,您將獲得一個賦值運算符調用,除非編譯器由於沒有副作用而可以安全地退出它。 在后一種情況下,編譯器可以自由選擇,但是根據定義,很難告訴您發生了什么。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM