禁用复制赋值的问题

如果在构造函数中用到了 new之类的初始化操作,在析构函数调用了delete.

如果没有禁用拷贝构造,复制赋值  那么在进行 
A a;    A b= a; 
操作时,
b 进行析构的时候,会把a 申请的内存给析构掉,会造成a 里面的对象已经释放,导致不可预计的结果。

 

class example
{
public:
	example()
	{
		base_ptr_ = new char[256];
		strcpy(base_ptr_,"lee");
	}
	void show()
	{
		printf("the name is %s\n",base_ptr_);
	}

	~example()
	{
		delete base_ptr_;
		base_ptr_ = NULL;
	}
private:
	char* base_ptr_;
	//	example(const example&);
	//	example operator = (const example&);
};

int _tmain(int argc, _TCHAR* argv[])
{
	example __ex1;
	__ex1.show();
	example __ex2 = __ex1;
	return 0;
}

当 __ex2 进行析构的话,就会出现二次删除的情况,base_ptr_ 已经在第一次的时候删除了。
<think>好的,用户想知道如何在C++中禁用类的赋值操作。我需要先回忆一下C++中禁用赋值操作符的方法。根据提供的引用,特别是引用[2]和引用[5],C++11之后可以使用`delete`关键字来显式删除赋值操作符。还有引用[4]提到可以用宏定义的方式,但可能不够直观。用户可能更关注现代C++的方法,即使用`delete`。 首先,要明确禁用赋值操作符的语法。在类定义中,将赋值操作符声明为`= delete`。这样编译器就不会生成默认的赋值操作,任何尝试进行赋值的行为都会导致编译错误。例如: class MyClass { public: MyClass& operator=(const MyClass&) = delete; }; 这样,任何对MyClass对象的赋值操作都会被禁止。同时,需要注意拷贝构造函数是否需要禁用,因为有时候需要同时禁用拷贝和赋值。引用[2]中的例子就同时禁用了拷贝构造和赋值操作符。 另外,用户可能想知道为什么要禁用赋值操作。可能涉及到资源管理,比如类持有唯一资源(如文件句柄、锁),复制会导致问题。引用[5]提到,如果类不应该被拷贝或赋值,应该使用`delete`来禁止,这有助于在编译时捕捉错误。 可能还需要提到旧版C++的方法,比如将赋值操作符声明为private但不实现,但引用[2]指出C++11之后推荐使用`delete`,所以应该优先推荐现代方法。 此外,用户可能混淆了移动赋值操作符和拷贝赋值操作符。引用[1]中提到了禁用移动赋值操作符,但问题主要是关于普通的拷贝赋值操作符。需要明确区分,但用户的问题可能更关注普通的赋值操作符。 最后,示例代码会有帮助,比如展示一个禁用赋值操作的类,并尝试赋值时导致的编译错误。这样可以直观地说明效果。同时,需要提醒用户如果需要同时禁用拷贝构造,也应该一并处理,如引用[2]中的例子。 总结回答的结构:先说明方法(使用`delete`),语法示例,解释作用,应用场景,注意事项,可能的相关问题。确保引用正确的参考文献,比如引用[2]和[5]来支持使用`delete`的方法。</think>在C++中禁用类的赋值操作符可通过以下方法实现: ### 一、禁用赋值操作符的核心方法 1. **使用`delete`关键字(C++11及以上推荐)** 在类声明中显式标记赋值操作符为`delete`: ```cpp class NonAssignable { public: NonAssignable() = default; // 禁用拷贝赋值操作符 NonAssignable& operator=(const NonAssignable&) = delete; }; ``` - **作用**:阻止编译器生成默认的赋值操作符,任何赋值操作会触发编译错误[^2][^5] - **示例报错**:`error: use of deleted function 'NonAssignable& NonAssignable::operator=(const NonAssignable&)'` 2. **传统方法:声明为`private`(C++03及之前)** ```cpp class LegacyClass { private: LegacyClass& operator=(const LegacyClass&); // 仅声明不实现 }; ``` - **局限**:友元类仍可能访问,不如`delete`彻底[^4] ### 二、禁用赋值操作符的典型场景 1. **资源唯一性要求** 如文件句柄、网络连接等独占资源类,防止误拷贝导致资源重复释放 2. **单例模式** 确保全局唯一实例无法被赋值: ```cpp class Singleton { public: static Singleton& getInstance() { /*...*/ } Singleton& operator=(const Singleton&) = delete; private: Singleton() = default; }; ``` 3. **包含不可拷贝成员** 若类成员(如`std::mutex`)不可拷贝,需连带禁用赋值操作符[^3] ### 三、注意事项 1. **连带禁用拷贝构造函数** 通常需同时禁用拷贝构造和赋值操作符以保证一致性[^2]: ```cpp class NonCopyable { public: NonCopyable(const NonCopyable&) = delete; NonCopyable& operator=(const NonCopyable&) = delete; }; ``` 2. **移动语义处理** 若需要支持移动语义,需单独定义`operator=(NonCopyable&&)`[^1] ### 四、相关扩展问题 1. **如何禁用移动赋值操作符?** 类似地使用`NonCopyable& operator=(NonCopyable&&) = delete;` 2. **是否可以用宏简化代码?** 可用宏批量禁用(但可读性降低): ```cpp #define DISALLOW_ASSIGN(TypeName) \ TypeName& operator=(const TypeName&) = delete class Example { DISALLOW_ASSIGN(Example); }; ```[^4] 通过上述方法,可以精确控制类的赋值行为,避免因意外拷贝导致的逻辑错误或资源泄漏。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值