最近我一直在研究Meyers的Effective C ++第三版。对于我目前正在处理的项目,我必须创建一个我明确要禁止使用编译器生成的函数的类。我在所述书中使用第6项实现了代码作为参考,唯一的主要区别在于我的类是模板化的。它的代码如下
template <class T>
class Uncopyable
{
protected:
Uncopyable<T>(){}
virtual ~Uncopyable<T>(){}
private:
Uncopyable<T>(const Uncopyable<T>&);
Uncopyable<T>& operator=(const Uncopyable<T>&);
};
我的测试功能。
class Test : private Uncopyable<Test>
{
public:
Test(){}
~Test(){}
inline void test()
{
std::cout << "blah" << std::endl;
}
private:
protected:
};
当像这样使用时,代码完全按预期工作
int main(int argc, char* argv[])
{
Test t1, t2;
// Works as expected, doesnt allow copying of object
t2 = t1;
// and this works fine, no copying
Test t3 = t2;
// finally, works correctly no copying is allowed
Test t4(t1);
return 0;
}
然而,当这样使用时,代码编译得很好并且复制可以发生,当它不应该时?
int main(int argc, char* argv[])
{
Test* t1 = new Test(), *t2;
t1->test();
// Works when it shouldnt work?
t2 = t1;
t2->test();
// same with this
Test* t3 = t2;
t3->test();
// and this
Test* t4(t1);
t4->test();
delete t1;
return 0;
}
我在没有模板类的情况下尝试过,结果是一样的,所以我认为不是问题。
那么,为什么允许这种情况发生呢?我的代码中是否有错误,或者我只是理解错误的概念?感谢。
答案 0 :(得分:4)
您正在复制指针,而不是对象。试试这个:
*t2 = *t1;
答案 1 :(得分:2)
您更改的代码是复制指针,而不是Test
对象本身。
t1
,t2
,t3
和t4
最终都指向相同的对象,并且永远不会复制此对象。< / p>
答案 2 :(得分:2)
这里有两件重要的事情:
拿这个块,例如:
Test* t1 = new Test(), *t2;
t1->test();
// Works when it shouldnt work?
t2 = t1;
此处未复制您的t1
对象。内存中只有一个类的实例,但现在有两个引用它。如果您在delete
上致电t2
,则会销毁该单个副本,而您的其他参考t1
现在将指向无效的内存位置。
我不确定你是否可以阻止原始指针的复制,但即使你可以让程序员轻而易举地将你的Test*
转换为void*
,也可以复制指针,然后再将其转换为Test*
。如果你想防止复制任何类型的引用,你需要使用智能指针和私有构造函数,这是一个全新的问题!
答案 3 :(得分:0)
编译器生成的函数在 C ++标准中被调用为特殊功能
乳清被强烈称为,特别是由于两个因素:
1。它们由编译器生成(如果不是由用户生成);
2。它们作为同一个类的参数对象(除了〜析构函数)。
因此,对于指针这样的函数未生成
同样在 C ++ 11标准中,您可以使用private
语句,而不是在delete
区域中声明要隐藏的功能。