1 c++中拷贝构造函数被调用的时机

拷贝构造函数被调用的几种情况:

(1)当用类的一个对象去初始化该类的另一个对象时,系统会自动调用拷贝构造函数

(2)将一个对象作为实参传递给一个非引用类型的形参,系统会自动调用拷贝构造函数;

(3)从一个返回类为非引用的函数返回一个对象时,系统会自动调用拷贝构造函数;

(4)用花括号列表初始化一个数组的元素时,系统会自动调用拷贝构造函数。

下面逐个举例:

1.1 当用类的一个对象去初始化该类的另一个对象时,系统会自动调用拷贝构造函数

#include<ctime>
#include<cstdlib>
#include<iterator>
#include<algorithm>
#include<iostream>
#include<numeric>
using namespace std;class MyClass {
public:MyClass():data(0){}MyClass(const MyClass& a){data = a.data;cout << "拷贝构造函数调用\n";}MyClass& operator=(const MyClass&a){data = a.data;cout << "调用赋值函数\n";return *this;}int data;
};int main() {MyClass a;MyClass b(a);          // 用类的一个对象a去初始化另一个对象bMyClass c = a;         // 用类的一个对象a去初始化另一个对象c,注意这里是初始化,不是赋值return 0;
}

测试

1.2 将一个对象作为实参传递给一个非引用类型的形参,系统会自动调用拷贝构造函数

#include<ctime>
#include<cstdlib>
#include<iterator>
#include<algorithm>
#include<iostream>
#include<numeric>
using namespace std;class MyClass {
public:MyClass():data(0){}MyClass(const MyClass& a){data = a.data;cout << "拷贝构造函数调用\n";}MyClass& operator=(const MyClass&a){data = a.data;cout << "调用赋值函数\n";return *this;}int data;
};void fun1(MyClass a) {return ;
}int main() {MyClass a;fun1(a);         // 形参为类对象,实参初始化形参,调用拷贝构造函数return 0;
}

测试

1.3 从一个返回类为非引用的函数返回一个对象时,系统会自动调用拷贝构造函数

第3点我看网上都这么说,但是实际调试的时候,发现不会调用拷贝构造函数,于是查了一下。这里默认情况下一般会被编译器优化,减少不必要的拷贝构造,所以,具体的返回值可能会因编译器及编译选项的不同而不同。使用g++编译器,关闭优化g++ xxx.cpp -fno-elide-constructors后执行结果如下(-fno-elide-constructors选项就是用来关闭拷贝优化的)

g++ xxx.cpp -fno-elide-constructors
#include<ctime>
#include<cstdlib>
#include<iterator>
#include<algorithm>
#include<iostream>
#include<numeric>
using namespace std;class MyClass {
public:MyClass():data(0){}MyClass(const MyClass& a){data = a.data;cout << "拷贝构造函数调用\n";}MyClass& operator=(const MyClass&a){data = a.data;cout << "调用赋值函数\n";return *this;}int data;
};MyClass fun2() {MyClass a;return a;
}int main() {MyClass a;MyClass d = fun2();    // 函数返回一个类对象时, 这里可能会被编译器优化,从而可能没有调用拷贝构造return 0;
}

不优化编译

这里拷贝构造调用两次,一次是返回非引用的对象时调用的,一次时用返回值初始对象d时调用的。

默认优化编译

什么都不调用。

编译器具体是怎么优化的,一般编译器会先看支不支持拷贝优化,如果不支持,再看有没有定义移动构造函数,如果都没有,就调用拷贝构造函数。更具体的细节可以参考移动语义及拷贝优化的内容。

1.4 用花括号列表初始化一个数组的元素时,系统会自动调用拷贝构造函数

#include<ctime>
#include<cstdlib>
#include<iterator>
#include<algorithm>
#include<iostream>
#include<numeric>
using namespace std;class MyClass {
public:MyClass():data(0){}MyClass(const MyClass& a){data = a.data;cout << "拷贝构造函数调用\n";}MyClass& operator=(const MyClass&a){data = a.data;cout << "调用赋值函数\n";return *this;}int data;
};int main() {MyClass a;MyClass b;MyClass arr[2] = {a, b};return 0;
}

编译

2 c++中有哪几种构造函数

  • 默认构造函数
  • 初始化构造函数(有参数)
  • 拷贝构造函数
  • 移动构造函数(move和右值引用)
  • 委托构造函数
  • 转换构造函数
#include <iostream>
using namespace std;
class Student{
public:// 默认构造函数,没有参数Student(){this->age = 20;this->num = 1000;}// 初始化构造函数,有参数和参数列表Student(int a, int n):age(a), num(n){};// 拷贝构造函数,这里与编译器生成的一致Student(const Student& s){this->age = s.age;this->num = s.num;}// 转换构造函数,形参是其他类型变量,且只有一个形参Student(int r){this->age = r;this->num = 1002;}~Student(){}
public:int age;int num;
};
int main(){Student s1;Student s2(18,1001);int a = 10;Student s3(a);Student s4(s3);printf("s1 age:%d, num:%d\n", s1.age, s1.num);printf("s2 age:%d, num:%d\n", s2.age, s2.num);printf("s3 age:%d, num:%d\n", s3.age, s3.num);printf("s2 age:%d, num:%d\n", s4.age, s4.num);return 0;
}

执行

  • 默认构造函数和初始化构造函数在定义类的对象,完成对象的初始化工作
  • 复制构造函数用于复制本类的对象
  • 转换构造函数用于将其他类型的变量,隐式转换为本类对象

3 有哪些情况必须用到成员列表初始化?作用是什么?

1) 必须使用成员初始化的四种情况:

  • 当初始化一个引用成员时;
  • 当初始化一个常量成员时;
  • 当调用一个基类的构造函数,而它拥有一组参数时;
  • 当调用一个成员类的构造函数,而它拥有一组参数时;

2) 成员初始化列表做了什么

  • 编译器会一一操作初始化列表,以适当的顺序在构造函数之内安插初始化操作,并且在任何显示用户代码之前;
  • list中的项目顺序是由类中的成员声明顺序决定的,不是由初始化列表的顺序决定的;

4 如果有一个空类,它会默认添加哪些函数

1) Empty();                          // 缺省构造函数
2) Empty( const Empty& );            // 拷贝构造函数
3) ~Empty();                         // 析构函数
4) Empty& operator=( const Empty& ); // 赋值运算符

5 如何设计一个类计算子类的个数

  • 为类设计一个static静态变量count作为计数器;
  • 类定义结束后初始化count=0;
  • 在构造函数中对count进行+1;
  • 设计拷贝构造函数,在进行拷贝构造函数中进行count +1,操作;
  • 在析构函数中对count进行-1;

6 如何阻止一个类被实例化?有哪些方法

  • 将类定义为抽象基类或者将构造函数声明为private;
  • 不允许类外部创建类对象,只能在类内部创建对象

7 如何禁止程序自动生成拷贝构造函数?

定义一个base类,在base类中将拷贝构造函数和拷贝赋值函数设置成private(或者delete掉),那么派生类中编译器将不会自动生成这两个函数,且由于base类中该函数是私有的(delete的),因此,派生类将阻止编译器执行相关的操作。

8 什么情况会自动生成默认构造函数

1) 带有默认构造函数的类成员对象,如果一个类没有任何构造函数,但它含有一个成员对象,而后者有默认构造函数,那么编译器就为该类合成出一个默认构造函数。不过这个合成操作只有在构造函数真正被需要的时候才会发生;如果一个类A含有多个成员类对象的话,那么类A的每一个构造函数必须调用每一个成员对象的默认构造函数而且必须按照类对象在类A中的声明顺序进行;
2) 带有默认构造函数的基类,如果一个没有任务构造函数的派生类派生自一个带有默认构造函数基类,那么该派生类会合成一个构造函数调用上一层基类的默认构造函数;
3) 带有一个虚函数的类
4) 带有一个虚基类的类

9 什么时候合成构造函数

1) 如果一个类没有任何构造函数,但他含有一个成员对象,该成员对象含有默认构造函数,那么编译器就为该类合成一个默认构造函数,因为不合成一个默认构造函数那么该成员对象的构造函数不能调用;
2) 没有任何构造函数的类派生自一个带有默认构造函数的基类,那么需要为该派生类合成一个构造函数,只有这样基类的构造函数才能被调用;
3) 带有虚函数的类,虚函数的引入需要进入虚表,指向虚表的指针,该指针是在构造函数中初始化的,所以没有构造函数的话该指针无法被初始化;
4) 带有一个虚基类的类。​​​​​​​

c++中拷贝构造函数被调用的时机相关推荐

  1. c/c++教程 - 2.4.2.3~4 拷贝构造函数的调用时机,构造函数调用规则

    目录 4.2.3 拷贝构造函数的调用时机 4.2.4 构造函数调用规则 相关教程 4.2.3 拷贝构造函数的调用时机 C++中拷贝构造函数调用时机,通常有三种情况: 使用一个已经创建完毕的对象来初始化 ...

  2. 拷贝构造函数的调用以及浅拷贝与深拷贝的理解

    今天一直在研究拷贝构造函数相关的东西,我这个大四老狗感觉又回到了大一学C++的时候.瞎捣鼓了一天,略微还是有些收获的,趁着脑子中的概念正热,把自己的心得赶紧整理出来分享给大家. ​       首先简 ...

  3. C++中拷贝构造函数

    C++中拷贝构造函数 拷贝构造函数根据名字可以看得出来,当对象发生拷贝时调用的函数.该函数与构造函数和析构函数一样,不会被显式调用.我们只是说当对象发生拷贝时调用,那么什么时候会发生对象拷贝呢?我们来 ...

  4. 深入探索C++对象模型一书中拷贝构造函数和NRV关系探讨

    转自:http://blog.guorongfei.com/2016/01/11/cpp-copy-constructor-nrv/ 最近深入探索C++对象模型一书,对于P67中最后一段话的第一句非常 ...

  5. C++拷贝构造函数的调用时机

    #define _CRT_SECURE_NO_WARNINGS #include<iostream> using namespace std;class Person { public:P ...

  6. 对象特性-----拷贝构造函数的调用

    C++中拷贝构造函数调用通常三种情况: ****使用一个已经创建完毕的对象来初始化一个新对象 ****值传递的方式给函数参数传值 ****以值方式返回局部对象 #include<iostream ...

  7. 理解C++中拷贝构造函数

    拷贝构造函数的功能是用一个已有的对象来初始化一个被创建的同样对象,是一种特殊的构造函数,具有一般构造函数的所有特性,当创建一个新对象的时候系统会自动调用它:其形参是本类对象的引用,它的特殊功能是将参数 ...

  8. C++中拷贝构造函数与赋值构造函数详解

    1.  拷贝构造函数 什么时候会调用拷贝构造函数  ?            使用一个已经创建好的对象来初始化一个新的对象. Student mya("zhang3",22);   ...

  9. C++中拷贝构造函数的形参为什么要是const引用

    1.首先为什么要是引用: 如对于 CBox(CBox initB);//复制构造函数一开始想到的原型 CBox cigar; CBox myBox(cigar); //如果编写这样一条语句 //那么将 ...

最新文章

  1. 图像检索中相似度度量公式:各种距离
  2. ANDROID L日志系统——JAVAAPI与LIBLOG
  3. mysql启动报错2002_mysql登陆启动报错 ERROR 2002 (HY000) 解决方法
  4. CST normalize S-parameter to given impedance
  5. ssl1341-最小路径覆盖【最大匹配,最小路径覆盖,图论】
  6. JAVA_if或者怎么用,Java If语句
  7. 图像语义分割 -- FCN
  8. 【Paper-Attack】MGA:Momentum Gradient Attack on Network
  9. android 仿美团悬浮,类似美团悬浮框的效果
  10. Bzoj3004 吊灯
  11. SpringCache实战遇坑
  12. URAL 1992 CVS 可持久化链栈
  13. Android NuPlayer播放框架
  14. PostgreSQL 之 CREATE FUNCTION
  15. TP框架使用qrcode生成二维码
  16. MIT Place Pulse数据集及google街景图片爬取
  17. esp32实现万能红外遥控器 基于开源红外码库IREXT
  18. linux修改系统语言为中文
  19. 教你如何布置家庭影院
  20. 【7gyy】解决Win8没声音,无法联网,分辨率问题的方法

热门文章

  1. 头歌实践-Java集合类之Set的HashSet之常用方法的使用
  2. 阿里双十一为首各巨头入场区块链 下半场真技术角逐开启
  3. lable-----qq聊天气泡圆角设置
  4. 蓝牙耳机比起有线耳机有什么优势?2020新款高续航低延迟蓝牙耳机分享
  5. java怎么输入_java中怎么输入?
  6. Android 超高仿微信图片选择器 图片该这么加载
  7. 获取java项目路径_Java获取项目路径
  8. 我分析了2万条饿了么、美团红包记录,这些是红包最多的APP(附数据集)
  9. 普通高校计算机软件人才创新培养模式研究与实践 罗宪 2010,《(高中阶段)拔尖创新人才培养的模式研究》结题报告...
  10. 把多余的内存空间虚拟成硬盘空间,享受飞一般的感觉!