![](/img/trans.png)
[英]Why is the copy-constructor not called when returning by-value a list-initialized object?
[英]Why isn't the copy-constructor called when passing rvalue by value to function
我以某種方式錯過了這件事,但我感到驚訝。 考慮以下代碼示例:
#include <iostream>
class A
{
int a;
public:
A(int a) : a(a) { std::cout << "Normal constructor called." << std::endl; }
A(const A& orig) : a(orig.a) { std::cout << "Copy constructor called." << std::endl; }
};
void testFunction1(const A arg) { std::cout << "testFunction1()" << std::endl; }
void testFunction2(const A& arg) { std::cout << "testFunction2()" << std::endl; }
int main()
{
testFunction1(A(2));
testFunction2(A(2));
return 0;
}
我期望得到以下結果:
/* Normal constructor called. */
/* Copy constructor called. */
/* testFunction1() */
/* Normal constructor called. */
/* testFunction2() */
但是我錯了。 確切的結果如下:
/* Normal constructor called. */
/* testFunction1() */
/* Normal constructor called. */
/* testFunction2() */
當我按值將A(2)
傳遞給testFunction1()
時,為什么不調用復制構造函數? 這是否意味着在C ++ 98中按值或引用傳遞右值之間沒有區別? 是優化嗎? A(2)
和arg
在testFunction1()
是否完全是同一對象?
是優化嗎?
是! 這稱為Copy Elision ,如果可能的話,可以根據編譯器刪除(繞過)副本。
因此,在您的情況下,編譯器知道無需調用復制構造函數即可擺脫該錯誤,並做到了這一點。 請注意,即使您使用arg
,例如調用A
的打印成員函數,出於優化目的,編譯器仍然可以使用復制省略。 換句話說,不使用arg
並不是此行為的原因。
如果您使用古老的編譯器,或者調整當前編譯器的設置,則可能會在一開始就看到期望的結果。
如Guillaume Racicot所述,使用c ++ 17可以確保在這種情況下進行復制省略。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.