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

article/2024/9/17 3:24:16

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) 带有一个虚基类的类。​​​​​​​


http://chatgpt.dhexx.cn/article/SxYHZA4O.shtml

相关文章

二说 拷贝构造函数 拷贝赋值函数

文章目录 什么是拷贝构造函数拷贝构造函数的调用时机2.1 当函数的参数为类的对象时2.2 函数的返回值是类的对象2.3 对象需要通过另外一个对象进行初始化 浅拷贝与深拷贝3.1 默认拷贝构造函数3.2 浅拷贝3.3 深拷贝3.4 防止默认拷贝发生 拷贝构造函数的几个细节4.1 为什么拷贝构造…

C++拷贝构造函数、构造函数和析构函数

一、拷贝构造函数 转载自&#xff1a;http://www.cnblogs.com/BlueTzar/articles/1223313.html 1、类对象的拷贝 对于普通类型的对象来说&#xff0c;它们之间的复制是很简单的&#xff0c;例如&#xff1a; int a88; int ba; 而类对象与普通对象不同&#xff0c;类对象内部…

拷贝构造函数起作用的三种情况

拷贝构造函数起作用的三种情况&#xff1a; 1.当用类的对象去初始化同类的另一个对象时。 Date d2(d1); Date d2 d1; //初始化语句&#xff0c;并非赋值语句。 2.当函数的形参是类的对象&#xff0c;调用函数进行形参和实参结合时。 void Func(A a1) //形参是类Date的对象…

【拷贝构造函数】c++类拷贝构造函数详解

【拷贝构造函数】c类拷贝构造函数详解 目录 【拷贝构造函数】c类拷贝构造函数详解一、什么是拷贝构造函数二、拷贝构造函数的几种调用时机1. 当函数的参数为类的对象时2. 函数的返回值是类的对象3. 当成员变量为类类型时4. 普通派生类构造函数的写法 三、浅拷贝与深拷贝1. 默认…

拷贝(复制)构造函数定义及3种调用情况举例

一、拷贝构造函数是一种特殊的构造函数&#xff0c;其形参为本类的对 象引用。 class 类名 { public : 类名&#xff08;形参&#xff09;&#xff1b;//构造函数 类名&#xff08;类名 &对象名&#xff09;&#xff1b;//拷贝构造函数 ... }&#xff1b; //拷贝构造函…

C++——拷贝构造函数详解

C——拷贝构造函数详解 1.拷贝构造函数的特点&#xff1a;2.通过例子引入拷贝构造&#xff1a;3构造对象的时候使用引用返回与不使用引用返回的问题&#xff1a;3.1不使用引用返回&#xff1a;3.2引用返回——从已经死亡的地址接收值不牢靠&#xff1a; 4.缺省的拷贝构造和等号…

C++ 拷贝构造函数详解

C 拷贝构造函数详解 下面的讲解将以C标准库的string类作为讲解对象&#xff0c;string类&#xff1a;class with pointer member(s) 1、拷贝构造函数和拷贝赋值函数 1.1引入 下面是给出的测试函数&#xff0c;也是我们要能在自己设计的myString类中实现的功能&#xff1a; …

详解析构函数、拷贝构造函数

目录 一.析构函数&#xff08;析构器&#xff09; &#xff08;一&#xff09;.使用方式及注意事项 1.使用方式 2.注意事项 &#xff08;二&#xff09;.默认析构函数 二.拷贝构造函数 &#xff08;一&#xff09;.使用方式及注意事项 1.使用方式 2.注意事项 &#xff0…

【深入理解C++】拷贝构造函数

文章目录 1.拷贝构造函数2.默认的拷贝操作3.默认拷贝构造函数4.何时调用拷贝构造函数 1.拷贝构造函数 拷贝构造函数是构造函数的一种。当利用已存在的对象创建一个新对象时&#xff0c;就会调用新对象的拷贝构造函数进行初始化。 拷贝构造函数的格式是固定的&#xff0c;即接…

C++拷贝构造函数详解

一. 什么是拷贝构造函数 首先对于普通类型的对象来说&#xff0c;它们之间的复制是很简单的&#xff0c;例如&#xff1a; int a 100; int b a; 而类对象与普通对象不同&#xff0c;类对象内部结构一般较为复杂&#xff0c;存在各种成员变量。 下面看一个类对象拷贝的简…

c++拷贝构造函数(深拷贝,浅拷贝)详解

一、什么是拷贝构造函数 首先对于普通类型的对象来说,它们之间的复制是很简单的,例如: int a=100; int b=a; 而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量。 下面看一个类对象拷贝的简单例子。 #include<iostream> using n…

YOLO 裂缝检测

环境 python3.5 yolov3 opencv keras

基于OpenCV的混凝土裂纹检测

基于OpenCV的混凝土裂纹检测 前言 这是我发的第一次博客&#xff0c;有什么建议大家可以给我留言&#xff0c;感激不尽! 接下来&#xff0c;我们进入正题。 一、使用函数库 numpy, opencv, heapq, skimage.morphology 二、使用步骤 1.初步预处理 初步预处理包括&#xf…

【图像识别】基于计算机视觉实现路面裂缝检测识别系统matlab代码

1 简介 随着公路与铁路事业的飞速发展,各类车辆和里程的增加,铁路的一次次提速,都对路面产生了巨大的压力。不论是公路路面还是铁路路面,路面裂纹都能随处可见,由路面裂纹造成的交通事故时有发生。研究路面裂纹检测方法对于路面维护、交通安全具有极其重大意义。近年来,路面裂…

基于计算机视觉的裂纹检测方案

点击上方“小白学视觉”&#xff0c;选择加"星标"或“置顶” 重磅干货&#xff0c;第一时间送达01. 数据集 我们首先需要从互联网上获取包含墙壁裂缝的图像&#xff08;URL格式&#xff09;数据。总共包含1428张图像&#xff1a;其中一半是新的且未损坏的墙壁&#x…

halcon裂纹缺陷检测

针对这一类表面的检测就不能单纯依靠帧差或者背景差来完成&#xff0c;因为背景的纹理不可能和当前图像的纹理完全相同。 方法一—局部阈值分割 一、局部阈值分割 1、gen_sin_bandpass–局部阈值分割 dyn_threshold(OrigImage, ThresholdImage : RegionDynThresh : Offset,…

使用 Python 进行深度学习以进行裂纹检测

使用 Python 进行深度学习以进行裂纹检测 问题陈述数据集准备训练模型结论参考 问题陈述 虽然新技术已经改变了我们生活的方方面面&#xff0c;在建筑领域似乎牛逼正在努力追赶。目前&#xff0c;建筑物的结构状况仍然主要是人工检查。简单来说&#xff0c;即使现在需要检查结…

Halcon-表面检测-----裂纹检测

对应示例程序&#xff1a; detect_mura_defects_blur.hdev 目标&#xff1a;实例实现LCD上有很多污点干扰下&#xff0c;检测LCD的印痕检测。 思路为&#xff1a;对LCD图像进行拆分&#xff0c;提取RGB三个分量。 对B分量进行处理&#xff0c;将其转换为频域内图像&#xff0…

图像中的裂纹检测

01. 数据集 我们首先需要从互联网上获取包含墙壁裂缝的图像(URL格式)数据。总共包含1428张图像:其中一半是新的且未损坏的墙壁;其余部分显示了各种尺寸和类型的裂缝。 第一步:读取图像,并调整大小。 images = []for url in tqdm.tqdm(df[content]): response = req…

html图片与文字轮播,我是这样写文字轮播的

原标题&#xff1a;我是这样写文字轮播的 作者&#xff1a;一半水一半冰 原文&#xff1a;http://www.cnblogs.com/jingh/p/6377736.html 1写在前面 最近总结下之前的工作&#xff0c;才恍然发现时间的流逝永远是悄无声息的&#xff0c;离开学校那座象牙塔已经也有大半年的时间…