直接初始化、拷贝初始化、赋值运算符

直接初始化、拷贝初始化、赋值运算符

5.1直接初始化:通过匹配构造函数参数,直接调用构造函数(包含拷贝构造函数)完成初始化。

5.2拷贝初始化:拷贝对象副本,或者对象右值引用,再通过调用拷贝构造函数或者移动构造函数实现初始化对象。

拷贝初始化发生的6种情况:

//other:已有的对象
T object = other;	//(1)	使用等号,且非引用类型
T object = {other};	//(2)	(until C++11)使用等号,且非引用类型
f(other)	//(3)做为对象为一个值,作为函数实参:值传递
return other;	//(4)//返回对象的值
throw object;
catch (T object)//(5)	对象作为值类型的异常
T array[N] = {other};	//(6)作为聚合初始化的一部分

对应的解释:

Copy initialization is performed in the following situations:

  1. when a named variable (automatic, static, or thread-local) of a non-reference type T is declared with the initializer consisting of an equals sign followed by an expression.

  2. (until C++11)when a named variable of a scalar type T is declared with the initializer consisting of an equals sign followed by a brace-enclosed expression (Note: as of C++11, this is classified as list initialization, and narrowing conversion is not allowed).

  3. when passing an argument to a function by value

  4. when returning from a function that returns by value

  5. when throwing or catching an exception by value

  6. as part of aggregate initialization, to initialize each element for which an initializer is provided

重点谈一下拷贝构造函数,定义如下:

A copy constructor is a special constructor for a class/struct that is used to make a copy of an existing instance.

翻译一下:拷贝构造函数是class/struct的一种特殊构造函数,拷贝构造函数通过拷贝(copy)已经出现的实例(对象)来实现构造,

foo (const foo&);//拷贝构造函数声明,foo类名,
//拷贝构造函数的形参必须是引用类型的原因:
// 如果不是引用类型,为了调用拷贝构造函数,我们必须拷贝它的实参,但为了拷贝实参,我们又需要调用拷贝构造函数,如此无限循环,造成错误。

拷贝初始化调用拷贝构造函数时,一定会先拷贝实例对象的临时副本,然后调用拷贝构造函数:可以观察拷贝初始化发生的6种情况,函数参数值传递、返回值一定会创建对象临时副本的情况。拷贝初始化利用拷贝构造函数时,应该是先调用对应的构造函数创建一个临时对象,然后拷贝构造函数(调用引用传递)再将构造的临时对象拷贝给要创建的对象。

再来看一下c++primer的例子,重点关注string s(dots);string s2 = dots; ,这两个都调用了拷贝构造函数,但是初始化方式不同。理解上面的内容,就比较好解释这种现象了:

string dots(10,'.');                //直接初始化
string s(dots);                     //直接初始化,直接匹配拷贝构造函数参数,进而直接调用拷贝构造函数,属于直接初始化
string s2 = dots;                   //拷贝初始化,先创建dots的副本,然后将副本做为参数传递给拷贝构造函数,属于拷贝初始化
string null_book = "9-999-99999-9"; //拷贝初始化,进行了隐式转换,即:char* to string
string nines = string(100,'9');     //拷贝初始化

**5.3赋值运算符:**使用一个对象赋值(=)给一个已经存在的对象。赋值和初始化有区别(参考前面的文章),因此拷贝初始化过程的=号不是赋值符号。

The equals sign,=,in copy-initialization of a named variable is not related to the assignment operator. Assignment operator overloads have no effect on copy-initialization.

拷贝构造函数与赋值运算符的区别
(1)从概念上区分:
拷贝构造函数是构造函数,而赋值操作符属于操作符重载范畴,它通常是类的成员函数

(2)从原型上来区分:
拷贝构造函数原型ClassType(const ClassType &);无返回值
赋值操作符原型ClassType& operator=(const ClassType &);返回值为ClassType的引用,便于连续赋值操作

(3)从使用的场合来区分:
拷贝构造函数用于产生对象,而赋值操作符要求‘=’的左右对象均已存在,它的作用就是把‘=’右边的对象的值赋给左边的对象。

拷贝构造函数是去完成对未初始化的存储区的初始化,而赋值操作符则是处理一个已经存在的对象。对一个对象赋值,当它一次出现时,它将调用拷贝构造函数,以后每次出现,都调用赋值操作符。

5.4参考

c++primer 13.1

cppreference
博客1
博客2
博客3

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值