這裏是一本書「C++陷阱」的項目56的摘錄:C++拷貝構造結構和指派問題
的情況並不少見看到一個簡單的 初始化書面 任何一個ÿ對象有三種不同的方式,就好像 它們是相同的。
Y a(1066);
Y b = Y(1066);
Y c = 1066;
就事實而言,所有這三個 初始化的可能會導致相同的目標代碼生成 ,但他們不等價的。 a的初始化被稱爲 直接初始化,它的確如人們所期望的那樣做 。 初始化通過 直接調用Y :: Y(int)來完成。
b和c的初始化爲 更復雜。事實上,他們太 複雜。這些都是複製 初始化。在 初始化B的情況下,我們請求 創立Y類型的匿名臨時 ,用值初始化 1066年,我們使用此匿名臨時作爲參數拷貝 構造函數Y級初始化 b。最後,我們稱這個匿名臨時文件爲 的析構函數。
爲了測試這個,我做了一個帶有數據成員的簡單類(最後附有程序),結果令人驚訝。看來對於c的情況,該對象是由拷貝構造函數構造的,而不是如書中所建議的。
有人知道語言標準是否已經改變,或者這只是編譯器的優化功能嗎?我是使用Visual Studio 2008的
代碼示例:
#include <iostream>
class Widget
{
std::string name;
public:
// Constructor
Widget(std::string n) { name=n; std::cout << "Constructing Widget " << this->name << std::endl; }
// Copy constructor
Widget (const Widget& rhs) { std::cout << "Copy constructing Widget from " << rhs.name << std::endl; }
// Assignment operator
Widget& operator=(const Widget& rhs) { std::cout << "Assigning Widget from " << rhs.name << " to " << this->name << std::endl; return *this; }
};
int main(void)
{
// construct
Widget a("a");
// copy construct
Widget b(a);
// construct and assign
Widget c("c");
c = a;
// copy construct!
Widget d = a;
// construct!
Widget e = "e";
// construct and assign
Widget f = Widget("f");
return 0;
}
輸出:
Constructing Widget a
Copy constructing Widget from a
Constructing Widget c
Assigning Widget from a to c
Copy constructing Widget from a
Constructing Widget e
Constructing Widget f
Copy constructing Widget from f
最令我通過構建d和e的結果感到驚訝。確切地說,我期待創建一個空對象,然後創建一個對象並將其分配給空對象。實際上,這些對象是由複製構造函數創建的。
「在初始化b的情況下,我們正在請求創建一個類型爲Y的匿名臨時文件,並使用值1066初始化」...並且在c的初始化過程中也是如此,只是很難看到暫時的。 – 2010-03-17 14:18:00
請注意,如果您的構造函數被聲明爲「explicit」,那麼'Y c = 1006'是不可能的,因爲大多數情況下,任何一個參數構造函數都應該這樣做。 – 2010-03-17 14:28:52
Matthieu,是的,我同意你所說的,我在編程時總是這麼做。如果我沒有記錯的話,你的觀點也包含在「更有效的C++」一書中。 – Andy 2010-03-17 14:39:21