为了禁止复制构建和复制作业,我看过boost noncopyable课程,并在Google格式指南中看到了DISALLOW_COPY_AND_ASSIGN宏。有没有理由更喜欢其中一种技术,或者应该注意的任何细微差别?
答案 0 :(得分:6)
我更喜欢在宏上提升不可复制,因为它不是宏,而且更容易(IMO)使用。
在实际代码中,我既没有使用它们也没有自己编写所需的两个声明。
但是,您可能感兴趣的一个细微差别是,当类本身尝试复制对象时,使用该宏或您自己的声明不会产生编译器错误(但是稍后无法链接)。 noncopyable
但是在这种情况下也会发出编译器错误信号,因为它是基类,其函数声明为private,而不是类本身。
答案 1 :(得分:3)
我总是将复制构造函数和赋值运算符设为私有,而不实现:
我还添加了一个明确的注释(就在复制构造函数和赋值运算符的原型之上),以表明我这样做是为了防止有人制作副本(作为对未来开发人员的提醒)。
在我看来,这个解决方案很明确,不依赖于外部库或宏,并且易于理解。
答案 2 :(得分:2)
基于尽可能避免继承的规则,我总是使用宏 - 在这种情况下是我自己的。当然,还有另一个关于避免使用宏的规则......
答案 3 :(得分:2)
我永远不会使用DISALLOW_COPY_AND_ASSIGN
宏,因为你必须把它放在类声明的private
部分。如果您(或维护代码的人)误将其放入public
部分,该怎么办?问题在于,“DISALLOW_COPY_AND_ASSIGN
”应该放在私有部分中并不明显:宏的名称似乎暗示它将不允许复制和赋值,而与您声明它的位置无关。 / p>
noncopyable
基类完全避免了这个问题。
但是,最快,最易读和可移植的方法是在类的私有部分中显式声明构造函数。
答案 4 :(得分:0)
这两种技术[实际上]是相同的。一个使用宏来保存键入(您仍然需要将它放在通常放置代码的位置),另一个通过您扩展的基类提供设施。
避免使用宏是一件好事,但扩展一个类只是为了避免将复制构造函数放在类的私有部分,这似乎让读者感到困惑。
你有什么理由不在你班上做这两种方法吗?
答案 5 :(得分:0)
请考虑以下代码(受到boost网站上noncopyable_test.cpp的启发):
#include <boost/noncopyable.hpp>
#include <iostream>
using namespace std;
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName&); \
void operator=(const TypeName&)
class BoostNoCopy : boost::noncopyable {
public:
BoostNoCopy() { cout << "BoostNoCopy failed." << endl; }
};
class MacroNoCopy {
public:
MacroNoCopy() { cout << "MacroNoCopy failed." << endl; }
private:
DISALLOW_COPY_AND_ASSIGN(MacroNoCopy);
};
class ExplicitNoCopy {
public:
ExplicitNoCopy() { cout << "ExplicitNoCopy failed." << endl; }
private:
ExplicitNoCopy(const ExplicitNoCopy&);
void operator=(const ExplicitNoCopy&);
};
int main() {
typedef BoostNoCopy NotCopyable;
NotCopyable a;
NotCopyable b(a);
a = b;
return 0;
}
通过将main()中的typedef设置为BoostNoCopy
,MacroNoCopy
或ExplicitNoCopy
,您会收到以下编译器错误(使用i686-apple-darwin11-llvm-g ++ - 4.2 ):
/usr/local/include/boost/noncopyable.hpp: In copy constructor ‘BoostNoCopy::BoostNoCopy(const BoostNoCopy&)’:
/usr/local/include/boost/noncopyable.hpp:27: error: ‘boost::noncopyable_::noncopyable::noncopyable(const boost::noncopyable_::noncopyable&)’ is private
main.cpp:9: error: within this context
main.cpp: In function ‘int main()’:
main.cpp:33: note: synthesized method ‘BoostNoCopy::BoostNoCopy(const BoostNoCopy&)’ first required here
/usr/local/include/boost/noncopyable.hpp: In member function ‘BoostNoCopy& BoostNoCopy::operator=(const BoostNoCopy&)’:
/usr/local/include/boost/noncopyable.hpp:28: error: ‘const boost::noncopyable_::noncopyable& boost::noncopyable_::noncopyable::operator=(const boost::noncopyable_::noncopyable&)’ is private
main.cpp:9: error: within this context
main.cpp: In function ‘int main()’:
main.cpp:34: note: synthesized method ‘BoostNoCopy& BoostNoCopy::operator=(const BoostNoCopy&)’ first required here
main.cpp: In function ‘int main()’:
main.cpp:18: error: ‘MacroNoCopy::MacroNoCopy(const MacroNoCopy&)’ is private
main.cpp:33: error: within this context
main.cpp:18: error: ‘void MacroNoCopy::operator=(const MacroNoCopy&)’ is private
main.cpp:34: error: within this context
main.cpp: In function ‘int main()’:
main.cpp:25: error: ‘ExplicitNoCopy::ExplicitNoCopy(const ExplicitNoCopy&)’ is private
main.cpp:33: error: within this context
main.cpp:26: error: ‘void ExplicitNoCopy::operator=(const ExplicitNoCopy&)’ is private
main.cpp:34: error: within this context
即使您可以解析使用boost :: noncopyable时给出的编译器错误,这样做肯定需要更长的时间。对于宏观和显式情况,错误非常明显。
因此,似乎权衡是boost :: noncopyable使用需要知道它的含义,如何使用,以及如何解析编译器错误;但是,它在代码中更加简洁。宏(谷歌/ Qt技术)需要宏定义(可能在其他一些标题中),以及如何使用它的知识;但是,编译器错误非常易读(与显式相同)。最后,显式技术最为明显,但可能需要程序员额外输入。