簡體   English   中英

const引用臨時和復制 - C ++

[英]const reference to temporary and copying - C++

請考慮以下代碼,

struct foo
{
    foo()
    {
        std::cout << "Constructing!" << std::endl;
    }

    foo(const foo& f)
    {
        std::cout << "Copy constructing!" << std::endl;
    }

    ~foo()
    {
        std::cout << "Destructing.." << std::endl;
    }
};

foo get()
{
    foo f;
    return f;
}

int main()
{
    const foo& f = get();
    std::cout << "before return" << std::endl;
    return 0;
}

MSVC上的輸出

Constructing!
Copy constructing!
Destructing..
before return
Destructing..

GCC的產出

Constructing!
before return
Destructing..

MSVC上的結果看起來不正確。

問題

  1. AFAIK,GCC在這里產生正確的結果。 為什么MSVC會給出不同的結果以及它為什么要進行復制構建?
  2. 由於返回值優化, const foo& f = get()const foo f = get()產生相同的輸出。 在這種情況下,應該首選哪種寫作方式?

有什么想法嗎..

您的MSVC構建沒有優化。 打開它們,你會得到相同的輸出。

默認情況下,GCC僅對您的臨時執行RVO。 它基本上是這樣做的:

const foo& f = foo();

MSVC不是。 它在函數中創建foo ,將其復制到函數外部(復制構造函數調用),破壞內部foo ,然后綁定引用。

兩個輸出都是正確的。 RVO是標准明確允許程序的可觀察行為發生變化的一個實例。

您正在看到返回值優化 ,這是一種復制省略 兩個程序都是正確的; 編譯器專門給出了一個消除臨時的選項,該臨時僅用於將數據從一個永久對象移動到另一個永久對象。

get()函數是構造本地(print Constructing!),並按值返回Foo對象。 必須創建返回的Foo對象,並通過復制構造(print copy construct!)完成。 請注意,這是在main中分配給const foo&f的對象值。

在進行該賦值之前,函數必須從get()返回,並且必須銷毀局部變量(即foo f;在get()中)。 (print 1st Destructing ..)從那里程序終止(即從main返回)然后get()返回並分配給“f”的對象被銷毀。 (打印第二次破壞...)

您看到兩個編譯器的輸出不同的原因是GCC正在優化get()的返回值,並且只是將const foo &f = get()替換為const foo &f = foo ;

1)這是因為不同的優化策略。 因為你沒有operator =,所以MSVC可以將代碼重構為const foo&f(get()),從而執行copy onstructor。 2)取決於你想要實現的目標:

const foo& f = get();
f = get(); // Incorrect, const references cannot be reassigned.
const foo g = get();
g = get(); // Correct.

暫無
暫無

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

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