直接初始化与拷贝(复制)初始化

来源:互联网 发布:云尚数据 编辑:程序博客网 时间:2024/05/22 16:01

std::set和std::map都有一个insert和emplace成员函数,那么,他们的区别是什么呢?

他们都往 set或map 里增加一个元素,区别在于新元素的构造上。emplace 使用直接构造,insert 使用复制(拷贝)构造。


那么直接构造和复制构造有什么区别呢?

认识这两种初始化(构造)有助于我们加深对语言的理解,可以更好的优化代码~

我们常见的几种初始化的形式:

string  str1 = "first";    //拷贝初始化,编译器允许把这句话改写为string str(“first”),但是string类必须有public的拷贝(移动)构造函数

string  str2(10,'a');     //直接初始化

string  str3(str2);      //直接初始化

string  str4 = string(10,'b');  //拷贝初始化

string  str5 = str4;        //拷贝初始化

string  str6 ("strr");       //直接初始化

 

开始不理解的朋友可能认为,调用拷贝构造函数就是拷贝初始化,所以可能觉得str3也是拷贝初始化,这样就错了~

 

直接初始化:

使用普通的函数匹配即可完成初始化。也就是说只是直接调用类的构造函数或拷贝构造函数就能完成初始化的就是直接初始化,我们的str2和str3分别调用构造函数贝构造函数

 

拷贝初始化:

将对象拷贝到正在创建的对象当中,如果需要还要进行类型转换。这里也就是间接调用拷贝构造函数,当然大部分情况调用拷贝构造函数,有时也可能调用移动构造函数。

 

根据上面的例子,我们可能觉得,只有等号"="出现时,才会是拷贝初始化。

其实不然,在下面三个情况下也会发生拷贝初始化。

1.将一个对象作为实参传递给一个非引用类型的实参(引用作为参数的话就可以省略拷贝这一操作,所以有时候可以这样来优化代码)

2.从一个返回类型为非引用的函数返回一个对象

3.花括号初始化一个数组的元素或一个聚合类(struct)的成员

 

区分二者的意义是什么?

对于内建类型来说,其实意义并不大,因为我们认为内建类型不存在构造函数一说,所以直接初始化也好,用等号初始化也好,复杂度可以认为没有区别。

而对于类类型的对象,拷贝初始化就相当于先创建一个对象(执行构造函数)再进行拷贝(执行拷贝构造函数),这样就相当于多执行了一步,效率自然就毕竟低。其实,对于一般的类来说也还好,也不费多少功夫,但是对于一个庞大复杂的继承类,构造一个对象可能需要向上多次构造基类,成员变量不断的申请内存与初始化,这样的步骤执行的多了肯定会影响效率的。

 

关于拷贝与赋值的使用提示:

类中有一个const或者引用成员,则类的合成拷贝赋值运算符也定义为删除的。

我们在写C++代码时,需要注意很多情况,像指针,引用,const这些关键字声明的变量都可能有很多陷阱。比如const对象作为成员变量,在赋值时就是错误的,所以默认的拷贝构造函数是无法解决的,编译器也就不会定义。同样,对于一个引用类型的成员变量,你即使给其赋值,只是改变引用原来绑定对象的初始值(引用初始化时必须绑定对象,而且始终绑定这个对象),这很可能不是我们的初衷,我们一般是想改变其所绑定的对象。所以默认的赋值运算符也是不存在的。

阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 屿组词 岁成语 岁的成语 岁开头成语 岁开头的成语 岁字开头成语 三岁儿童成语接龙大全 带岁的成语 岁字开头的成语 岁开头的成语接龙 岁月号事件 岁月号 岁月拼音 岁月意思 岁月是把 激情岁月原型 激情岁月演员 激情岁月介绍 激情岁月片尾曲 激情的岁月演员 我们的法兰西岁月 激情的岁月连续剧 我的特种岁月 激情的岁月原型 平凡的岁月 我的青年岁月 2岁宝宝简笔画 岁笔画 岁的笔画 岁笔画顺序 1一3岁简笔画鱼图片 1一3岁简笔画教程 岁笔顺 岁的笔顺 岁字笔顺 岁笔顺怎么写 岁的笔顺笔画顺序 6岁生日写朋友圈怎么写 4岁幼儿在家表现怎么写 12岁英语怎么写 4岁孩子不写作业怎么办