直接初始化与拷贝(复制)初始化
2016-01-19 20:57
225 查看
认识这两种初始化有助于我们加深对语言的理解,可以更好的优化代码~
我们常见的几种初始化的形式:
string str1 = "first";
//拷贝初始化
string str2(10,'a');
//直接初始化
string str3(str2);
//直接初始化
string str4 = string(10,'b');
//拷贝初始化
string str5 = str4;
//拷贝初始化
string str6 ("strr");
//直接初始化,但是string类必须有public的拷贝(移动)构造函数
开始不理解的朋友可能认为,调用拷贝构造函数就是拷贝初始化,所以可能觉得str3也是拷贝初始化,这样就错了~
直接初始化:
使用普通的函数匹配即可完成初始化。也就是说只是直接调用类的构造函数或拷贝构造函数就能完成初始化的就是直接初始化,我们的str2和str3分别调用构造函数和拷贝构造函数
拷贝初始化:
将对象拷贝到正在创建的对象当中,如果需要还要进行类型转换。这里也就是间接调用拷贝构造函数,当然大部分情况调用拷贝构造函数,有时也可能调用移动构造函数。
根据上面的例子,我们可能觉得,只有等号"="出现时,才会是拷贝初始化。
其实不然,在下面三个情况下也会发生拷贝初始化。
1.将一个对象作为实参传递给一个非引用类型的实参(引用作为参数的话就可以省略拷贝这一操作,所以有时候可以这样来优化代码)
2.从一个返回类型为引用的函数返回一个对象
3.花括号初始化一个数组的元素或一个聚合类(struct)的成员
区分二者的意义是什么?
对于内建类型来说,其实意义并不大,因为我们认为内建类型不存在构造函数一说,所以直接初始化也好,用等号初始化也好,复杂度可以认为没有区别。
而对于类类型的对象,拷贝初始化就相当于先创建一个对象(执行构造函数)再进行拷贝(执行拷贝构造函数),这样就相当于多执行了一步,效率自然就毕竟低。其实,对于一般的类来说也还好,也不费多少功夫,但是对于一个庞大复杂的继承类,构造一个对象可能需要向上多次构造基类,成员变量不断的申请内存与初始化,这样的步骤执行的多了肯定会影响效率的。
关于拷贝与赋值的使用提示:
类中有一个const或者引用成员,则类的合成拷贝赋值运算符也定义为删除的。
我们在写C++代码时,需要注意很多情况,像指针,引用,const这些关键字声明的变量都可能有很多陷阱。比如const对象作为成员变量,在赋值时就是错误的,所以默认的拷贝构造函数是无法解决的,编译器也就不会定义。同样,对于一个引用类型的成员变量,你即使给其赋值,只是改变引用原来绑定对象的初始值(引用初始化时必须绑定对象,而且始终绑定这个对象),这很可能不是我们的初衷,我们一般是想改变其所绑定的对象。所以默认的赋值运算符也是不存在的。
我们常见的几种初始化的形式:
string str1 = "first";
//拷贝初始化
string str2(10,'a');
//直接初始化
string str3(str2);
//直接初始化
string str4 = string(10,'b');
//拷贝初始化
string str5 = str4;
//拷贝初始化
string str6 ("strr");
//直接初始化,但是string类必须有public的拷贝(移动)构造函数
开始不理解的朋友可能认为,调用拷贝构造函数就是拷贝初始化,所以可能觉得str3也是拷贝初始化,这样就错了~
直接初始化:
使用普通的函数匹配即可完成初始化。也就是说只是直接调用类的构造函数或拷贝构造函数就能完成初始化的就是直接初始化,我们的str2和str3分别调用构造函数和拷贝构造函数
拷贝初始化:
将对象拷贝到正在创建的对象当中,如果需要还要进行类型转换。这里也就是间接调用拷贝构造函数,当然大部分情况调用拷贝构造函数,有时也可能调用移动构造函数。
根据上面的例子,我们可能觉得,只有等号"="出现时,才会是拷贝初始化。
其实不然,在下面三个情况下也会发生拷贝初始化。
1.将一个对象作为实参传递给一个非引用类型的实参(引用作为参数的话就可以省略拷贝这一操作,所以有时候可以这样来优化代码)
2.从一个返回类型为引用的函数返回一个对象
3.花括号初始化一个数组的元素或一个聚合类(struct)的成员
区分二者的意义是什么?
对于内建类型来说,其实意义并不大,因为我们认为内建类型不存在构造函数一说,所以直接初始化也好,用等号初始化也好,复杂度可以认为没有区别。
而对于类类型的对象,拷贝初始化就相当于先创建一个对象(执行构造函数)再进行拷贝(执行拷贝构造函数),这样就相当于多执行了一步,效率自然就毕竟低。其实,对于一般的类来说也还好,也不费多少功夫,但是对于一个庞大复杂的继承类,构造一个对象可能需要向上多次构造基类,成员变量不断的申请内存与初始化,这样的步骤执行的多了肯定会影响效率的。
关于拷贝与赋值的使用提示:
类中有一个const或者引用成员,则类的合成拷贝赋值运算符也定义为删除的。
我们在写C++代码时,需要注意很多情况,像指针,引用,const这些关键字声明的变量都可能有很多陷阱。比如const对象作为成员变量,在赋值时就是错误的,所以默认的拷贝构造函数是无法解决的,编译器也就不会定义。同样,对于一个引用类型的成员变量,你即使给其赋值,只是改变引用原来绑定对象的初始值(引用初始化时必须绑定对象,而且始终绑定这个对象),这很可能不是我们的初衷,我们一般是想改变其所绑定的对象。所以默认的赋值运算符也是不存在的。
相关文章推荐
- 决策树 算法 理论
- matlab中 bsxfun函数
- 绘图(CGContext)
- codefor 14D:树的直径
- 两日问题总结
- leetcode之Lowest Common Ancestor of a Binary Search Tree
- 【JavaWeb Structs2学习】 addFieldError以及ValueStack (应用:接受参数进行判断返回结果输出至页面)
- android 源码剖析之------Window的内部实现机制(添加、删除、更新)
- 第十章 五种并发包总结
- 随记
- Eclipse常用快捷键
- 11078 Open Credit System
- 一张图概括iOS知识点
- CodeForces 603A_Alternative Thinking (DP)
- 进一步理解C++构造与析构
- 求C++数组长度问题
- 2014百度校园招聘面试题
- web安全浅析
- C++11新特性应用--介绍几个新增的便利算法(用于分区的几个算法)
- U盘启动android 5.0