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

一、拷贝构造函数调用的时机

? 当以拷贝的方式初始化对象时会调用拷贝构造函数,这里需要注意两个关键点,分别是以拷贝的方式初始化对象

1. 初始化对象

初始化对象是指,为对象分配内存后第一次向内存中填充数据,这个过程会调用构造函数,对象被创建后必须立即初始化。也就是说只要创建对象就会调用构造函数。

2.初始化和赋值的区别

初始化和赋值都是将数据写入内存中,从表面看,初始化在很多时候都是以复制的方式来实现的,很容易引起混淆。在定义的同时进行复制叫做初始化,定义完成以后再赋值(不管定义的时候有没有赋值)就叫做赋值。初始化只能由一次,赋值可以由很多次。具体可以看下面的示例。

int a = 100;  //以赋值的方式初始化
a = 200;  //赋值
a = 300;  //赋值
int b;  //默认初始化
b = 29;  //赋值
b = 39;  //赋值

? 对于基本的数据类型,我们很少会区分初始化和赋值,即使是混淆了,也不会出现什么错误。但是对于类,他们的区别就非常重要了,因为初始化时会调用构造函数(以拷贝的方式初始化时会调用拷贝构造函数),而赋值时会调用重载过的赋值运算符。

二、拷贝构造函数和普通构造函数调用的例子

#include<iostream>
#include<string>

using namespace std;

class Student {
public:
    Student(string name = "", int age = 0); //普通构造函数
    Student(const Student &Stu); //拷贝构造函数
    Student& operator=(const Student &Stu); // 重载 = 运算符
    void display();

private:
    string m_name;
    int m_age;

};

//普通构造函数
Student::Student(string name , int age )
{
    m_name = name;
    m_age = age;
}

//拷贝构造函数
Student::Student(const Student &Stu)
{
    this->m_name = Stu.m_name;
    this->m_age = Stu.m_age;

    cout << "Copy constructor was called." << endl;
}

// 重载 = 运算符
Student& Student:: operator=(const Student &Stu)
{
    this->m_name = Stu.m_name;
    this->m_age = Stu.m_age;

    cout << "operator=() was called." << endl;

    return *this;
}

void Student::display()
{
    cout << m_age << "  " << m_age << endl;
}

int main()
{
    Student stu1("Xiao Ming", 18);  // 调用普通构造函数
    Student stu2("Xiao Wang", 18);  // 调用普通构造函数

    Student stu3 = stu1;  // 调用拷贝构造函数
    stu3 = stu2;  //调用operator=()

    Student stu4(stu1);   // 调用拷贝构造函数

    Student stu5; // 调用普通构造函数
    stu5 = stu2;  //调用operator=()

    return 0;
}

/*
输出:
    Copy constructor was called.
    operator=() was called.
    Copy constructor was called.
    operator=() was called.

*/

三、以拷贝的方式初始化对象

1. 初始化对象时会调用构造函数,不同的初始化方式会调用不同的构造函数:
  • 如果用传递进来的实参初始化对象,那么会调用普通的构造函数。
  • 如果用现有对象的数据来初始化对象,就会调用拷贝构造函数,这就是以拷贝的方式初始化对象。
2. 以拷贝的方式来初始化对象的几种情况:
  1. 将其它对象作为实参。

    Student stu1("Xiao Ming", 18);  // 普通初始化
    Student stu4(stu1);   // 以拷贝的方式进行初始化
    /* 即使我们不在类中显示定义拷贝构造函数,这种初始化方式也是有效的,编译器会生成默认的拷贝构造函数 */
  2. 在创建对象的同时赋值。
    Student stu1("Xiao Ming", 18);  // 普通初始化
    Student stu3 = stu1;  // 以拷贝的方式进行初始化
    /* 这是最常见的一种以拷贝的方式初始化对象的情况 */
  3. 函数的形参为类类型。

    如果函数的形参为类类型(对象),那么调用函数时要将另外一个对象作为实参传递进来赋值给形参,这也是以拷贝的方式初始化形参对象,如下所示。

    void func(Student s){
        //TODO:
    }
    Student stu1("Xiao Ming", 18);  // 普通初始化
    func(stu1);  //以拷贝的方式初始化
    
    /* func() 函数有一个 Student 类型的形参 s,将实参 stu 传递给形参 s 就是以拷贝的方式初始化的过程。 */
  4. 函数返回值为类类型(与编译器有关不绝对)

    ? 当函数的返回值为类类型时,return 语句会返回一个对象,不过为了防止局部对象被销毁,也为了防止通过返回值修改原来的局部对象,编译器并不会直接返回这个对象,而是根据这个对象先创建出一个临时对象(匿名对象),再将这个临时对象返回。而创建临时对象的过程,就是以拷贝的方式进行的,会调用拷贝构造函数,如下所示。

    Student func(){
       Student stu1("Xiao Ming", 18);  // 普通初始化
        return stu1;
    }
    Student stu = func();

原文地址:https://www.cnblogs.com/ay-a/p/10415808.html

时间: 2024-10-13 01:27:45

C++拷贝构造函数的调用时机的相关文章

【校招面试 之 C++】第4题 拷贝构造函数被调用的3个时机

1.被调用的3个时机: (1)直接初始化或拷贝初始化: (2)将一个对象作为一个实参传递,形参采用非指针或非引用的对象进行接收时: (3)函数的返回值是一个非指针或者非对象被接收时. 2.举例说明: #include <iostream> using namespace std; class Test{ private: int a; int b; static int count; public: Test(int i, int j): a(i), b(j){} void print();

构造函数的调用时机(一)

构造函数是C++类的重要组成部分,起着初始化对象的作用.当对象生成的时候,编译器会自动调用对象的构造函数,完成对象的初始化工作.根据对象的不同作用域和声明周期,可以将对象分为一下几种: 1.局部对象 2.堆对象 3.全局对象 4.静态对象 下面我们将以反汇编(VC6.0)的形式,查看局部对象的调用时机 #include <stdio.h> class CDemo { public: CDemo() { m_nInt = 100; } private: int m_nInt; }; int ma

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

c++拷贝构造函数(深拷贝,浅拷贝)详解 2013-11-05 20:30:29 分类: C/C++ 原文地址:http://blog.chinaunix.net/uid-28977986-id-3977861.html 一.什么是拷贝构造函数      首先对于普通类型的对象来说,它们之间的复制是很简单的,例如: int a=100; int b=a; 而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量.  下面看一个类对象拷贝的简单例子. #include<iostream

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

一.什么是拷贝构造函数      首先对于普通类型的对象来说,它们之间的复制是很简单的,例如: int a=100; int b=a; 而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量.  下面看一个类对象拷贝的简单例子. #include<iostream> using namespace std; class CExample { private: int a; public: //构造函数 CExample(int b) { a=b; printf("con

C++拷贝构造函数(深拷贝与浅拷贝)

转自http://blog.csdn.net/lwbeyond/article/details/6202256/ 一. 什么是拷贝构造函数 对于普通类型的对象来说,它们之间的复制是很简单的,例如:int a=88;int b=a; 而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量.下面看一个类对象拷贝的简单例子. 1 #include <iostream> 2 using namespace std; 3 4 class CExample { 5 private: 6 in

C++拷贝构造函数详解

一. 什么是拷贝构造函数 首先对于普通类型的对象来说,它们之间的复制是很简单的,例如: int a = 100; int b = a; 而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量.下面看一个类对象拷贝的简单例子. #include <iostream> using namespace std; class CExample { private: int a; public: //构造函数 CExample(int b) { a = b;} //一般函数 void Sh

08--C++拷贝构造函数详解

C++拷贝构造函数详解 一. 什么是拷贝构造函数 首先对于普通类型的对象来说,它们之间的复制是很简单的,例如: [c-sharp] view plain copy int a = 100; int b = a; 而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量.下面看一个类对象拷贝的简单例子. [c-sharp] view plain copy #include <iostream> using namespace std; class CExample { private

C++——拷贝构造函数说明

一. 什么是拷贝构造函数 首先对于普通类型的对象来说,它们之间的复制是很简单的,例如: [c-sharp] view plaincopy 1 int a = 100; 2 int b = a; 而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量. 下面看一个类对象拷贝的简单例子. [c-sharp] view plaincopy 3 #include <iostream> 4 using namespace std; 5 6 class CExample { 7 privat

[016]转--C++拷贝构造函数详解

一. 什么是拷贝构造函数 首先对于普通类型的对象来说,它们之间的复制是很简单的,例如: [c-sharp] view plaincopy int a = 100; int b = a; 而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量.下面看一个类对象拷贝的简单例子. [c-sharp] view plaincopy #include <iostream> using namespace std; class CExample { private: int a; publi