网站首页 > 基础教程 正文
默认情况下,c++编译器至少为我们的类提供3个函数
1.默认构造函数(无参,函数体为空)
2.默认析构函数(无参,函数体为空)
3.默认拷贝构造函数,对类中非静态成员属性简单值拷贝
如果用户定义拷贝构造函数,c++不会再提供任何默认构造函数
如果用户定义了普通构造(非拷贝),c++不再提供默认无参构造,但是会提供默认拷贝构造
其中“默认拷贝构造函数,对类中非静态成员属性简单值拷贝” 这一点指的是,当我们没有为类显式定义拷贝构造函数时,C++ 编译器会自动生成一个默认的拷贝构造函数。这个默认的拷贝构造函数会逐个拷贝类中的非静态成员变量,但它仅仅做的是浅拷贝,即简单地将一个对象的成员变量的值赋给另一个对象。
1.拷贝构造函数的作用
拷贝构造函数是用来创建一个新对象,并使用已有的对象来初始化它。也就是说,拷贝构造函数定义了如何根据一个已有的对象来生成该对象的副本。
2.默认拷贝构造函数的行为
默认拷贝构造函数执行的是成员逐个拷贝(浅拷贝),即对于类中的每个非静态成员,直接调用它们各自的拷贝构造函数。编译器只会简单地将源对象的每个非静态成员的值赋给目标对象。
例如,假设我们有一个类如下:
class MyClass {
public:
int a;
float b;
};
如果你写代码如下:
MyClass obj1;
obj1.a = 10;
obj1.b = 5.5f;
MyClass obj2 = obj1; // 调用默认拷贝构造函数
在这个过程中,编译器为 MyClass 自动生成的默认拷贝构造函数可能看起来像这样:
MyClass::MyClass(const MyClass& other) {
this->a = other.a; // 简单地将 obj1 的 a 赋值给 obj2 的 a
this->b = other.b; // 简单地将 obj1 的 b 赋值给 obj2 的 b
}
这里的 obj2 是通过拷贝 obj1 初始化的,obj2 的 a 和 b 成员的值分别是 obj1 中相应成员的值。
3.浅拷贝与深拷贝的区别
默认的拷贝构造函数进行的仅是浅拷贝。这在类的成员是基础数据类型(如 int、float)时没有问题,但如果类中有指针或动态分配的资源时,浅拷贝可能会引发问题。
class MyClass {
public:
int* ptr;
MyClass(int val) {
ptr = new int(val);
}
~MyClass() {
delete ptr;
}
};
假设我们有这样一个类,其中 ptr 是指向动态分配的内存。当我们执行拷贝时,默认的拷贝构造函数只会简单地复制指针的值,两个对象的 ptr 都指向同一块内存。这样会导致问题:
MyClass obj1(5);
MyClass obj2 = obj1; // 调用默认拷贝构造函数,执行浅拷贝
其中obj1 和 obj2 的 ptr 指针指向同一块内存。如果 obj1 被析构,它会释放那块内存,而 obj2 仍然持有一个无效的指针。这就会导致双重释放(double free)或悬空指针问题。
4.解决方案:深拷贝
为了避免指针或动态资源的共享问题,当类涉及到动态资源时,应该自己定义拷贝构造函数,执行深拷贝,即为每个对象单独分配新的内存,并拷贝数据。
MyClass::MyClass(const MyClass& other) {
ptr = new int(*other.ptr); // 分配新的内存,并拷贝内容
}
这样,每个对象都有自己独立的资源,互不干扰。
so
默认拷贝构造函数进行的是浅拷贝,即对类中的非静态成员做简单的逐成员赋值。
猜你喜欢
- 2024-10-12 全面剖析 C++ Boost 智能指针!| CSDN 博文精选
- 2024-10-12 C++设计模式——原型模式 设计模式之原型模式
- 2024-10-12 如何攻克 C++ 中复杂的类型转换? c++中四种类型转换的方式
- 2024-10-12 C++|由成员函数到运算符重载(类内、类外、友元方式重载)
- 2024-10-12 C++11新特性(49)- 用移动类对象代替拷贝类对象
- 2024-10-12 C++类的默认成员函数 c++类中定义的成员默认访问属性为( )
- 2024-10-12 C++的23种设计模式(上篇-创建型模式)
- 2024-10-12 C++构造函数和析构函数详解 c语言构造函数和析构函数
- 2024-10-12 c++——默认成员函数 c++成员变量默认值
- 2024-10-12 C++|类中实现操作符重载,用操作符代替成员函数名
- 最近发表
- 标签列表
-
- gitpush (61)
- pythonif (68)
- location.href (57)
- tail-f (57)
- pythonifelse (59)
- deletesql (62)
- c++模板 (62)
- css3动画 (57)
- c#event (59)
- linuxgzip (68)
- 字符串连接 (73)
- nginx配置文件详解 (61)
- html标签 (69)
- c++初始化列表 (64)
- exec命令 (59)
- canvasfilltext (58)
- mysqlinnodbmyisam区别 (63)
- arraylistadd (66)
- node教程 (59)
- console.table (62)
- c++time_t (58)
- phpcookie (58)
- mysqldatesub函数 (63)
- window10java环境变量设置 (66)
- c++虚函数和纯虚函数的区别 (66)