禁用copy构造函数

如果你定义一个空类,编译器自动为你做的就是申明四个函数,分别是:

1,构造函数

2,copy构造函数

3,copy assignment构造函数

4,析构函数

比如:

class Moon{}


这是一个空类,然后编译器会为你做的就是像下面这么写:

class Moon{
public:
    // 构造函数
    Moon(){} 
    // 拷贝构造函数
    Moon(const Moon &yueliang){}
    // 复制赋值函数
    Moon &operator=(const Moon &yueliang){}
    // 析够函数
    ~Moon(){}
}

上面的类是Moon,客观真理告诉我们月亮不可能被复制构造另一个,所以对于不能含有复制构造函数的类,在C++中有两种较为标准的写法:

1,定义一个公共基类,继承这个基类就能禁止复制构造,如:

class Celestial{
protected:
    Celestial(){}
    ~Celestial(){}
private:
    Celestial(const Celestial&){}
    Celestial& operator=(const Celestial&){}
}

class Moon:private Celestial{

}

2,创建一个宏,将其放到独一无二的对象的private中:

#define NO_COPY(Typename) Typename(const Typename&); void operator=(const Typename&);

据董的博客所说,第二种方式较好。

此内容为《董的博客》的effective c++部分所理解提成。


<think>嗯,用户现在想了解拷贝构造函数的使用。之前他们问过关于C++的printf输出整型数,现在转向了更基础的C++概念,拷贝构造函数。这说明用户可能在学习C++的基础知识,或者是想加深对面向对象编程的理解。我需要先回顾拷贝构造函数的定义、用途和常见使用场景。 首先,拷贝构造函数是一种特殊的构造函数,用于创建一个新对象作为现有对象的副本。用户可能想知道为什么需要它,以及如何正确使用它。需要解释它的语法,参数必须是同类对象的引用,通常是const引用,避免修改原对象。 接下来,用户可能对什么时候会调用拷贝构造函数感兴趣。常见的情况包括对象作为函数参数传递、从函数返回对象,以及显式地用另一个对象初始化新对象。比如,当用Existing obj2 = obj1;这样的语句时,拷贝构造函数会被调用。 然后,需要区分浅拷贝和深拷贝。浅拷贝只是复制指针的值,而深拷贝会复制指针指向的内容。如果类中有动态分配的资源,比如堆内存,就必须自定义拷贝构造函数来实现深拷贝,避免多个对象指向同一内存区域导致的问题。比如,默认的拷贝构造函数可能引发双重释放的错误,这时候用户必须自己实现深拷贝。 用户可能对如何编写拷贝构造函数的具体代码示例感兴趣。比如,给一个包含指针成员的类,展示如何正确分配内存并复制数据。还要提到拷贝构造函数的声明语法,如ClassName(const ClassName& other),并展示如何在其中处理资源分配。 此外,需要注意拷贝构造函数与赋值运算符的区别。拷贝构造函数用于初始化新对象,而赋值运算符用于已存在的对象之间的赋值。有时候用户可能会混淆这两者,需要明确区分。 用户可能还想知道何时需要自定义拷贝构造函数。通常,当类管理资源(如动态内存、文件句柄等)时,必须自定义拷贝构造函数、拷贝赋值运算符和析构函数,即“三法则”。现在C++11之后还有“五法则”,加入了移动构造函数和移动赋值运算符,但可能暂时不需要深入到这里。 另外,可以提到C++11引入的显式删除拷贝构造函数的情况,比如当禁止对象拷贝时,使用= delete。或者在某些情况下使用默认的拷贝构造函数,使用= default。 可能用户在实际编程中遇到了问题,比如程序崩溃或者资源管理错误,这时候正确的拷贝构造函数实现可以解决问题。需要强调正确管理资源的重要性,避免内存泄漏或重复释放。 总结来说,回答需要包括拷贝构造函数的定义、使用场景、深浅拷贝的区别、必要时的自定义实现,以及示例代码。同时,对比默认拷贝构造函数的潜在问题,强调资源管理的重要性。最后,可能推荐使用现代C++的特性如智能指针来避免手动管理资源,但用户的问题可能更关注基础,所以先集中在拷贝构造函数本身。</think>在 C++ 中,**拷贝构造函数**(Copy Constructor)是用于通过已有对象初始化新对象的特殊构造函数。以下是详细说明: --- ### 一、基本定义 #### 语法 ```cpp class ClassName { public: // 拷贝构造函数声明 ClassName(const ClassName& other); }; // 拷贝构造函数实现 ClassName::ClassName(const ClassName& other) { // 拷贝逻辑(如深拷贝资源) } ``` - **参数**:必须是同类对象的 `const` 引用(避免拷贝无限递归) - **调用时机**:当通过已有对象初始化新对象时自动触发 --- ### 二、调用场景 #### 1. 显式初始化 ```cpp ClassName obj1; ClassName obj2 = obj1; // 调用拷贝构造函数 ClassName obj3(obj1); // 直接调用拷贝构造函数 ``` #### 2. 函数传参 ```cpp void func(ClassName obj); // 参数传递时会调用拷贝构造函数 ClassName myObj; func(myObj); // 触发拷贝构造函数 ``` #### 3. 函数返回对象(未优化时) ```cpp ClassName createObj() { ClassName obj; return obj; // 可能触发拷贝构造函数(依赖编译器优化) } ``` --- ### 三、深浅拷贝问题 #### 默认行为(浅拷贝) 若未显式定义拷贝构造函数,编译器会生成默认版本,**逐成员复制**。 **风险**:如果类管理资源(如动态内存),浅拷贝会导致多个对象指向同一资源: ```cpp class ShallowCopy { private: int* data; // 动态分配的内存 public: ShallowCopy(int val) { data = new int(val); } ~ShallowCopy() { delete data; } // 析构释放内存 }; int main() { ShallowCopy a(10); ShallowCopy b = a; // 默认浅拷贝:b.data 和 a.data 指向同一内存 // 程序结束时,同一内存被释放两次 → 崩溃! } ``` #### 解决方案(深拷贝) 自定义拷贝构造函数,独立复制资源: ```cpp class DeepCopy { private: int* data; public: DeepCopy(int val) { data = new int(val); } // 自定义拷贝构造函数 DeepCopy(const DeepCopy& other) { data = new int(*other.data); // 分配新内存并复制值 } ~DeepCopy() { delete data; } }; ``` --- ### 四、关键注意事项 1. **必须处理资源** 若类包含动态内存、文件句柄等资源,必须显式定义拷贝构造函数(和析构函数、赋值运算符)。 2. **避免自拷贝** 确保拷贝构造函数能正确处理 `other` 是自身的情况(罕见但需预防)。 3. **性能优化** 频繁拷贝可能影响性能,可通过 `const引用传参` 或使用移动语义(C++11 的 `移动构造函数`)优化。 --- ### 五、示例代码 ```cpp #include <iostream> class String { private: char* buffer; int length; public: String(const char* str) { length = strlen(str); buffer = new char[length + 1]; strcpy(buffer, str); } // 自定义拷贝构造函数(深拷贝) String(const String& other) { length = other.length; buffer = new char[length + 1]; strcpy(buffer, other.buffer); } ~String() { delete[] buffer; } void print() { std::cout << buffer << std::endl; } }; int main() { String s1("Hello"); String s2 = s1; // 调用拷贝构造函数 s2.print(); // 输出 "Hello" return 0; } ``` --- ### 六、禁用拷贝构造函数 若禁止对象拷贝,可显式删除拷贝构造函数: ```cpp class NonCopyable { public: NonCopyable(const NonCopyable&) = delete; NonCopyable& operator=(const NonCopyable&) = delete; }; ``` --- ### 总结表:默认拷贝 vs 自定义拷贝 | 类型 | 行为 | 适用场景 | 风险 | |--------------|-------------------|------------------------|--------------------| | 默认拷贝 | 浅拷贝(逐成员复制) | 无资源管理的简单类 | 资源重复释放/泄漏 | | 自定义拷贝 | 深拷贝(独立资源) | 管理动态资源、文件句柄等 | 需手动管理资源逻辑 | **建议**:遵循“三法则”(自定义拷贝构造函数、拷贝赋值运算符、析构函数)以确保资源安全。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值