在c++ 11中禁用复制类的最简洁的方法
Most concise way to disable copying class in C++11
当存在用户定义的析构函数时,我有一个问题处理自c++ 11以来默认生成的复制构造函数和复制赋值操作符。
对于大多数足够简单的类,默认生成的构造函数、操作符和析构函数就可以了。考虑以下声明析构函数的原因:
-
使普通析构函数在基类中为虚函数:
// header class Base1 { public: virtual ~Base1() = default; }; class Base2 { public: virtual ~Base2(); }; // source Base2::~Base2() = default;
在这些情况下,编译器会生成所有4个复制和移动特殊方法吗?如果是,那么我认为这很好,没有必要使
Base1
或Base2
复杂化。 -
在析构函数中打印调试信息:
// header class D { public: ~D(); }; // source D::~D() { #ifdef DEBUG_THIS std::cout << "D was destructed." << std::endl; #endif }
我相信在这种情况下会生成复制构造函数和赋值操作符;但是move构造函数和赋值操作符不能。我想避免使用过时的默认生成并禁用
D
的复制。我还想避免用4个deleted
声明淹没D
。禁用一个复制构造函数是否足够?这是一种好风格吗?
对于c++ 11,一个干净的方法是遵循boost中使用的模式(参见这里)
创建一个基类,删除复制构造函数和复制赋值,并继承它:
class non_copyable
{
protected:
non_copyable() = default;
~non_copyable() = default;
non_copyable(non_copyable const &) = delete;
void operator=(non_copyable const &x) = delete;
};
class MyClass: public non_copyable
{
...
}
删除复制构造函数和复制赋值操作符是禁用复制的最简单、最清晰的方法:
class X
{
X(X const &) = delete;
void operator=(X const &x) = delete;
};
我不明白你在问题体中的虚析构函数是什么意思。这听起来像是你在要求一种方法,使你的代码占用更少的源代码字符,但也更神秘的任何人看它。
如果删除的函数列表让您感到困扰,我猜您可以将它们隐藏在宏后面。
#define NON_COPYABLE_NOR_MOVABLE(T)
T(T const &) = delete;
void operator=(T const &t) = delete;
T(T &&) = delete;
-
当显式默认了析构函数时,只生成复制构造函数和复制赋值操作符。即便如此,他们这一代也不受待见。因此,为了拥有虚析构函数和所有默认方法,应该这样写:
struct Base { Base()=default; virtual ~Base() = default; Base(const Base&)=default; Base& operator=(const Base&)=default; Base(Base&&)=default; Base& operator=(Base&&)=default; };
我肯定会使用一个以上的宏
Base
类。 -
如果析构函数是用户定义的,仍然会生成2个特殊的方法。有以下方法可以禁用已弃用的生成复制构造函数和复制赋值操作符:
-
delete移动构造函数或移动赋值操作符(不太清楚,但很短):
Base(Base&&)=delete; // shorter than deleting assignment operator
-
delete 复制构造函数和复制赋值操作符:
Base(const Base&)=delete; Base& operator=(const Base&)=delete;
请注意,如果需要,必须显式声明默认构造函数,例如
Base()=default;
。宏或继承特殊类也可以用于此目的,但我个人更喜欢删除移动构造函数来实现我自己的宏或基类。当使用Qt或boost时,我更喜欢分别继承
Q_DISABLE_COPY(Base)
和boost::noncopyable
,因为它们已经实现,广为人知且可识别。 -
http://accu.org/index.php/journals/1896 -这些问题的详细解释和基本原理。
你可以这样做(这是Caffe使用的:一个快速开放的深度学习框架):
// Disable the copy and assignment operator for a class.
#define DISABLE_COPY_AND_ASSIGN(classname)
private:
classname(const classname&);
classname& operator=(const classname&)
使用例子:
class CNoCopyable{
public:
CNoCopyable(int i):m_d(i){}
private:
int m_d;
// add this line(pass class name)
DISABLE_COPY_AND_ASSIGN(CNoCopyable);
};
- 为不同配置设置MSVC_RUNTIME_LIBRARY的正确方法是什么
- 通过方法访问结构
- 声明高维向量的更简洁的方法
- 使用通用函数指针参数化函数模板的简洁方法
- 在 Clang 中禁用特定警告实例的简洁方法
- 将多个值与同一变量进行比较时'!='运算符最简洁的方法是什么?
- 确定程序本身是否具有对文件的特定访问权限的最简洁的方法是什么
- 犰狳C ++:将矩阵的每一行乘以向量的高效简洁的方法
- Rcpp:比较从 R 数据帧派生的字符串的简洁方法
- 是否有一种简洁的方法可以将文本输出到调试窗格
- 编写 if then else 类型语句的简洁方法
- 在可变参数模板中使用填充程序的更简洁方法
- 在构造过程中是否有一种简洁的方法可以派生成员的类型?
- c++:访问大型数据集中的重成员变量的最有效和简洁的方法
- 清除地图和删除内容的最简洁的方法是什么?
- C++ 我知道数组长度,但想知道是否是一种更简洁的数组元素定义方法
- 最简洁的检查一个数是否落在其他两个数之间的方法
- 将空范围传递给接受一对迭代器的函数的干净/简洁的方法是什么?
- 在c++ 11中禁用复制类的最简洁的方法
- 简洁的计算 #define 方法