復制初始化使用=符號,而直接初始化將初始化式放在圓括號中。
(1)對於一般的內建類型,這兩種初始化基本上沒有區別。
int a(5);//直接初始化
int a=5;//復制初始化
int a=int (5);//直接初始化
(2)當用於類類型對象時,初始化的復制形式和直接形式有所不同:直接初始化直接調用與實參匹配的構造函數,復制初始化總是調用復制構造函數。復制初始化首先使用指定構造函數創建一個臨時對象,然后使用復制構造函數將那個臨時對象復制到正在創建的對象。
string null_book = "9-999-99999-9 ";//copy-initialization
string dots(10, '. ');//direct-initialization
string empty_copy = string();//先direct,然后copy-initialization
string empty_direct;//direct-initialization
對於類類型對象,只有指定單個實參或顯式創建一個臨時對象用於復制時,才使用復制初始化。
創建dots時,調用參數為一個數量和一個字符的string構造函數並直接初始化dots的成員。創建null_book時,編譯器首先調用接受一個C風格字符串形參的string構造函數,創建一個臨時對象,然后,編譯器使用string復制構造函數將null_book初始化為那個臨時對象的副本。
empty_copy和empty_direct的初始化都調用默認構造函數。對前者初始化時,默認構造函數創建一個臨時對象,然后復制構造函數用該對象初始化empty_copy。對后者初始化時,直接運行empty_direct的默認構造函數。
支持初始化的復制形式主要是為了與C的用法兼容。當情況許可時,可以允許編譯器跳過復制構造函數直接創建對象,但編譯器沒有義務這樣做。
通常直接初始化和復制初始化僅在低級別優化上存在差異。然而,對於不支持復制的類型,或者使用非explicit構造函數的時候,它們有本質區別:
ifstream file1("filename");//ok:direct initialization
ifstream file2 = "filename";//error:copy constructor is private
//This initialization is okay only if the sales_item(const string&) constructor is not explicit
Sales_item item = string("9-999-99999-9");
...
item的初始化是否正確,取決於正在使用哪個版本的Sales_item類。某些版本將參數為一個string的構造函數定義為explicit。如果構造函數是顯示的,則初始化失敗;如果構造函數不是顯示的,則初始化成功。
對於復制初始化,最顯示的調用手段就是使用“=”符號(這個時候應該成為復制初始化符號)。那么還有許多地方是隱式的調用。如參數傳遞時,函數返回時,初始化容器時!
1)對於參數傳遞:我們知道除非是引用參數,否則就是一個使用上層對象復制初始化函數參數的過程。
2)對於函數返回值:我們知道除非是引用返回,否則在return的那個語句就是使用函數內的對象,復制初始化一個上層對象(通常是臨時的,然后馬上有被用於)
3)在某些容器初始化的過程中如:
vect<string> svec(5);
這里的過程就是,先使用string默認構造出一個實例對象,然后使用這個對象,復制初始化其它的元素。這個過程是容器的實現細節,其實從外面看,可以理解為直接初始化。
4)數組初始化,有時候使用這樣的語法:
Sales_item primer_eds[]={ string("1231231"),
string("3123123")
}
可知這個過程,就是一個先調用直接初始化生成string,然后繼續隱式調用直接初始化生成Sales_item。最后使用復制初始化,給那個數組的各個元素初始化。
(1)對於一般的內建類型,這兩種初始化基本上沒有區別。
int a(5);//直接初始化
int a=5;//復制初始化
int a=int (5);//直接初始化
(2)當用於類類型對象時,初始化的復制形式和直接形式有所不同:直接初始化直接調用與實參匹配的構造函數,復制初始化總是調用復制構造函數。復制初始化首先使用指定構造函數創建一個臨時對象,然后使用復制構造函數將那個臨時對象復制到正在創建的對象。
string null_book = "9-999-99999-9 ";//copy-initialization
string dots(10, '. ');//direct-initialization
string empty_copy = string();//先direct,然后copy-initialization
string empty_direct;//direct-initialization
對於類類型對象,只有指定單個實參或顯式創建一個臨時對象用於復制時,才使用復制初始化。
創建dots時,調用參數為一個數量和一個字符的string構造函數並直接初始化dots的成員。創建null_book時,編譯器首先調用接受一個C風格字符串形參的string構造函數,創建一個臨時對象,然后,編譯器使用string復制構造函數將null_book初始化為那個臨時對象的副本。
empty_copy和empty_direct的初始化都調用默認構造函數。對前者初始化時,默認構造函數創建一個臨時對象,然后復制構造函數用該對象初始化empty_copy。對后者初始化時,直接運行empty_direct的默認構造函數。
支持初始化的復制形式主要是為了與C的用法兼容。當情況許可時,可以允許編譯器跳過復制構造函數直接創建對象,但編譯器沒有義務這樣做。
通常直接初始化和復制初始化僅在低級別優化上存在差異。然而,對於不支持復制的類型,或者使用非explicit構造函數的時候,它們有本質區別:
ifstream file1("filename");//ok:direct initialization
ifstream file2 = "filename";//error:copy constructor is private
//This initialization is okay only if the sales_item(const string&) constructor is not explicit
Sales_item item = string("9-999-99999-9");
...
item的初始化是否正確,取決於正在使用哪個版本的Sales_item類。某些版本將參數為一個string的構造函數定義為explicit。如果構造函數是顯示的,則初始化失敗;如果構造函數不是顯示的,則初始化成功。
對於復制初始化,最顯示的調用手段就是使用“=”符號(這個時候應該成為復制初始化符號)。那么還有許多地方是隱式的調用。如參數傳遞時,函數返回時,初始化容器時!
1)對於參數傳遞:我們知道除非是引用參數,否則就是一個使用上層對象復制初始化函數參數的過程。
2)對於函數返回值:我們知道除非是引用返回,否則在return的那個語句就是使用函數內的對象,復制初始化一個上層對象(通常是臨時的,然后馬上有被用於)
3)在某些容器初始化的過程中如:
vect<string> svec(5);
這里的過程就是,先使用string默認構造出一個實例對象,然后使用這個對象,復制初始化其它的元素。這個過程是容器的實現細節,其實從外面看,可以理解為直接初始化。
4)數組初始化,有時候使用這樣的語法:
Sales_item primer_eds[]={ string("1231231"),
string("3123123")
}
可知這個過程,就是一個先調用直接初始化生成string,然后繼續隱式調用直接初始化生成Sales_item。最后使用復制初始化,給那個數組的各個元素初始化。
這兒是對復制構造函數和復制初始化的介紹:
http://www.cnblogs.com/xkfz007/archive/2012/03/01/2376376.html
下面是一個測試構造函數的類:
#include <iostream>
using namespace std;
class A{
friend ostream& operator<<(ostream& os, const A& rhs);
public:
A( int a= 10):m_a(a){
id=count++;
cout<< " A(int a):id= "<<id<<endl;
}
A( const A& rhs):m_a(rhs.m_a){
id=count++;
cout<< " A(const A&rhs):id= "<<id<<endl;
}
A& operator=( const A& rhs){
if( this !=&rhs){
id=count++;
m_a=rhs.m_a;
}
return * this;
}
~A(){
cout<< " ~A:id= "<<id<<endl;
}
private:
int m_a;
int id;
static int count;
};
int A::count= 0;
ostream& operator<<(ostream& os, const A& rhs){
os<< " <A:m_a= "<<rhs.m_a<< " ,id= "<<rhs.id<< " > ";
return os;
}
int main1(){
A a1;
cout<<a1<<endl;
A a2=a1;
cout<<a2<<endl;
A a3;
cout<<a3<<endl;
a3=a2;
cout<<a3<<endl;
A a4(a3);
cout<<a4<<endl;
return 0;
}
int main(){
A a1,a2( 5),a3( 200);
A b=A( 8000);
cout<<b<<endl;
A arr[]={a1,a2,a3};
int i( 5),j= 5;
int k= int();
cout<<i<<j<<k<<endl;
}
using namespace std;
class A{
friend ostream& operator<<(ostream& os, const A& rhs);
public:
A( int a= 10):m_a(a){
id=count++;
cout<< " A(int a):id= "<<id<<endl;
}
A( const A& rhs):m_a(rhs.m_a){
id=count++;
cout<< " A(const A&rhs):id= "<<id<<endl;
}
A& operator=( const A& rhs){
if( this !=&rhs){
id=count++;
m_a=rhs.m_a;
}
return * this;
}
~A(){
cout<< " ~A:id= "<<id<<endl;
}
private:
int m_a;
int id;
static int count;
};
int A::count= 0;
ostream& operator<<(ostream& os, const A& rhs){
os<< " <A:m_a= "<<rhs.m_a<< " ,id= "<<rhs.id<< " > ";
return os;
}
int main1(){
A a1;
cout<<a1<<endl;
A a2=a1;
cout<<a2<<endl;
A a3;
cout<<a3<<endl;
a3=a2;
cout<<a3<<endl;
A a4(a3);
cout<<a4<<endl;
return 0;
}
int main(){
A a1,a2( 5),a3( 200);
A b=A( 8000);
cout<<b<<endl;
A arr[]={a1,a2,a3};
int i( 5),j= 5;
int k= int();
cout<<i<<j<<k<<endl;
}