构造函数

分类

C++中有一下几类构造函数

以一下这个类为例:

1
2
3
4
class Person{
int age;
std::string name;
};

1.默认构造函数

没有参数,用于创建一个具有默认值的Person对象。

1
Person()=default;

2.参数化构造函数

1
Person(int a, std::string n) : age(a), name(n) {}

3.拷贝构造函数

使用另一个对象来初始化当前对象。

1
Person(const Person& other) : age(other.age), name(other.name) {}

如果没有显示的定义拷贝构造函数,编译器会生成一个默认的拷贝构造函数,这个默认的拷贝构造函数会逐个成员地复制传入对象的成员变量

3.1浅拷贝

浅拷贝是指在复制对象时,只复制对象的成员变量的值,而不会复制对象所指向的动态分配的内存。如果对象中包含指针成员,浅拷贝只会复制指针本身的值,也就是说,复制后的对象和原始对象==共享同一块动态分配的内存==

3.2深拷贝

深拷贝是指在复制对象时,不仅复制对象的成员变量的值,还会复制对象所指向的动态分配的内存。如果对象中包含指针成员,深拷贝会为复制的对象分配新的内存,并复制原始对象的内存内容到新分配的内存中

默认的拷贝构造函数,由于是逐个成员地复制传入对象的成员变量,所以肯定是浅拷贝

总结:

  • 浅拷贝可能导致原始对象和复制对象共享资源,如果管理不当,可能会导致内存泄漏或不一致的问题。
  • 深拷贝确保每个对象都有自己的资源副本,但可能会增加复制的开销,因为需要为每个指针分配新的内存并复制内容。

3.3赋值操作符

赋值运算符的功能其实和和拷贝构造函数类似,只是构造函数用在初始化时,赋值运算符用在其他场合:

1
2
3
4
5
6
Person& operator=(const Person& other)
{
this->age = other.age;
this->name = other.name;
return *this;
}

编译器为类生成的默认赋值运算符,也是浅拷贝

4.移动构造函数

使用右值引用来接收一个临时的Person对象,并将其资源转移给当前对象。==用于移动语义==

1
2
3
4
Person(Person&& other) noexcept : age(other.age), name(std::move(other.name)) {
other.age = 0; // 将原对象的年龄置为0
other.name = ""; // 将原对象的名字置为空字符串
}

5.构造函数的调用时机

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/* 1.括号法*/
Person P1; //默认构造函数,不要加括号!!
Person P2(10); //有参构造
Person P3(P1); //拷贝构造
Person P4(std::move(P1)); //移动构造


/* 2.显示法*/
Person P4 = Person(10); //有参构造
Person P5 = Person(P4); //拷贝构造
Person P10(std::move(P5)); //移动构造

/* 3.隐式转换法*/
Person P6 = 10;//有参构造,相当于:Person P6 = Person(10);
Person P7 = P6;//拷贝构造
Person P7 = std::move(P1);//移动构造