c++中的直接初始化与复制初始化
2011-11-01 19:16
274 查看
按照C++ Primer第四版中文版13.1节中的说法:
1.对象的定义
回忆一下,C++支持两种初始化形式(2.3.3节):直接初始化和复制初始化。复制初始化使用=符号,而直接初始化将初始化式放在圆括号中。
当用于类类型对象时,初始化的复制形式和直接形式有所不同:直接初始化直接调用与实参匹配的构造函数,复制初始化总是调用复制构造函数。复制初始化首先使用指定构造函数创建一个临时对象(7.3.2节),然后使用复制构造函数将那个临时对象复制到正在创建的对象:
string null_book = "9-999-99999-9 ";//copy-initialization
string dots(10, '. ');//direct-initialization
string empty_copy = string();//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构造函数(12.4.4节)的时候,它们有本质区别:
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。如果构造函数是显示的,则初始化失败;如果构造函数不是显示的,则初始化成功。
C/C++ code
#include <iostream>
using std::cout;
using std::endl; class test
{
public:
test(int i):ival(i){cout < < "调用了以一个int为形参的构造函数 " < <endl;}
test(const test& t):ival(t.ival){cout < < "调用了复制构造函数 " < <endl;}
void operator = (const test& t)// 定义一个赋值操作符函数
{
ival = t.ival;
cout < < "调用了赋值操作符=函数 " < <endl;
}
private:
int ival;
};
int main(int argc,char * argv[])
{
test t1 = 1; //仅调用ival(1)
t1 = 2; //调用ival(2)产生临时对象后
//在调用operator = 函数完成赋值操作
test t2(t1); //调用test(int i)对t2进行初始化
return 0;
}
对于test t2 = test(1); 语句
因为是初始化,根据c++语法编译器解析时确定它的确应该
调用复制构造函数test(const test& t),所以当,test(const test& t) 拷贝构造函数为private时会编译出错,但是,编译器在代码生成时会做一定的优化,不同的编译器这种优化程度也可能不同,如是对于test t2 = test(1);初始化过程所需要产生不必要临时对象的过程被优化掉了,而其实际调用过程同test t1 = 1;初始化的调用是一样的,看以下的反汇编代码:
test t1 = test(1);
//可以看出这一段代码和下一段test t3 = 1;的反汇编代码一样
//而其调用过程也是一样的
0041182E push 1
00411830 lea ecx,[t1]
00411833 call test::test (4111C7h) //调用test(int i)
test t3 = 1;
00411838 push 1
0041183A lea ecx,[t3]
0041183D call test::test (4111C7h) //调用test(int i)
t1 = 2; //调用ival(2)产生临时对象后
00411842 push 2
00411844 lea ecx,[ebp-0ECh]
0041184A call test::test (4111C7h) //调用test(int i)
0041184F lea eax,[ebp-0ECh]
00411855 push eax
00411856 lea ecx,[t1]
00411859 call test::operator= (4111EAh) //在调用operator = 函数完成赋值操作
test t2(t1); //调用test(int i)对t2进行初始化
0041185E lea eax,[t1]
00411861 push eax
00411862 lea ecx,[t2]
00411865 call test::test (41125Dh) //调用test(const test& t)
A f=22;
按常理,先生成一个临时对象,用22初始化,既相当于A f=A(22);
然后调用拷贝构造函数,将f初始化
但是由于编译器的优化,如果一个临时变量直接赋值给一个刚生成的还未初始化的变量时(这里是f),会直接把临时量构造在未初始化的对象所在内存中,所以只调用了依次构造函数而已
这样省掉一块内存空间,而且少调用了一次构造函
1.对象的定义
回忆一下,C++支持两种初始化形式(2.3.3节):直接初始化和复制初始化。复制初始化使用=符号,而直接初始化将初始化式放在圆括号中。
当用于类类型对象时,初始化的复制形式和直接形式有所不同:直接初始化直接调用与实参匹配的构造函数,复制初始化总是调用复制构造函数。复制初始化首先使用指定构造函数创建一个临时对象(7.3.2节),然后使用复制构造函数将那个临时对象复制到正在创建的对象:
string null_book = "9-999-99999-9 ";//copy-initialization
string dots(10, '. ');//direct-initialization
string empty_copy = string();//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构造函数(12.4.4节)的时候,它们有本质区别:
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。如果构造函数是显示的,则初始化失败;如果构造函数不是显示的,则初始化成功。
C/C++ code
#include <iostream>
using std::cout;
using std::endl; class test
{
public:
test(int i):ival(i){cout < < "调用了以一个int为形参的构造函数 " < <endl;}
test(const test& t):ival(t.ival){cout < < "调用了复制构造函数 " < <endl;}
void operator = (const test& t)// 定义一个赋值操作符函数
{
ival = t.ival;
cout < < "调用了赋值操作符=函数 " < <endl;
}
private:
int ival;
};
int main(int argc,char * argv[])
{
test t1 = 1; //仅调用ival(1)
t1 = 2; //调用ival(2)产生临时对象后
//在调用operator = 函数完成赋值操作
test t2(t1); //调用test(int i)对t2进行初始化
return 0;
}
对于test t2 = test(1); 语句
因为是初始化,根据c++语法编译器解析时确定它的确应该
调用复制构造函数test(const test& t),所以当,test(const test& t) 拷贝构造函数为private时会编译出错,但是,编译器在代码生成时会做一定的优化,不同的编译器这种优化程度也可能不同,如是对于test t2 = test(1);初始化过程所需要产生不必要临时对象的过程被优化掉了,而其实际调用过程同test t1 = 1;初始化的调用是一样的,看以下的反汇编代码:
test t1 = test(1);
//可以看出这一段代码和下一段test t3 = 1;的反汇编代码一样
//而其调用过程也是一样的
0041182E push 1
00411830 lea ecx,[t1]
00411833 call test::test (4111C7h) //调用test(int i)
test t3 = 1;
00411838 push 1
0041183A lea ecx,[t3]
0041183D call test::test (4111C7h) //调用test(int i)
t1 = 2; //调用ival(2)产生临时对象后
00411842 push 2
00411844 lea ecx,[ebp-0ECh]
0041184A call test::test (4111C7h) //调用test(int i)
0041184F lea eax,[ebp-0ECh]
00411855 push eax
00411856 lea ecx,[t1]
00411859 call test::operator= (4111EAh) //在调用operator = 函数完成赋值操作
test t2(t1); //调用test(int i)对t2进行初始化
0041185E lea eax,[t1]
00411861 push eax
00411862 lea ecx,[t2]
00411865 call test::test (41125Dh) //调用test(const test& t)
A f=22;
按常理,先生成一个临时对象,用22初始化,既相当于A f=A(22);
然后调用拷贝构造函数,将f初始化
但是由于编译器的优化,如果一个临时变量直接赋值给一个刚生成的还未初始化的变量时(这里是f),会直接把临时量构造在未初始化的对象所在内存中,所以只调用了依次构造函数而已
这样省掉一块内存空间,而且少调用了一次构造函
相关文章推荐
- C++的一大误区——深入解释直接初始化与复制初始化的区别
- C++的一大误区——深入解释直接初始化与复制初始化的区别
- C++的一大误区——深入解释直接初始化与复制初始化的区别
- C++的一大误区——深入解释直接初始化与复制初始化的区别
- C++直接初始化和复制初始化
- c++直接初始化和复制初始化 理解
- C++直接初始化和复制初始化1
- C++的一大误区——深入解释直接初始化与复制初始化的区别
- C++直接初始化和复制初始化2
- C++中直接初始化与复制初始化
- C++的一大误区——深入解释直接初始化与复制初始化的区别
- C++的一大误区——深入解释直接初始化与复制初始化的区别
- C++的一大误区——深入解释直接初始化与复制初始化的区别
- C++直接初始化与复制初始化的区别深入解析
- C++直接初始化和复制初始化
- C++ 直接初始化和复制初始化
- C++的一大误区——深入解释直接初始化与复制初始化的区别
- C++的一大误区——深入解释直接初始化与复制初始化的区别
- C++误区——直接初始化和复制初始化
- C++的一大误区-深入理解直接初始化与复制初始化的区别