禁用复制构造函数

时间:2011-05-20 20:15:04

标签: c++ copy-constructor

我有一个班级:

class SymbolIndexer {
protected:
  SymbolIndexer ( ) { }

public:
  static inline SymbolIndexer & GetUniqueInstance ( ) 
  { 
    static SymbolIndexer uniqueinstance_ ;
    return uniqueinstance_ ; 
  }
};

如何修改它以禁用以下代码:

SymbolIndexer symbol_indexer_ = SymbolIndexer::GetUniqueInstance ( );

并且仅允许代码:

SymbolIndexer & ref_symbol_indexer_ = SymbolIndexer::GetUniqueInstance ( );

4 个答案:

答案 0 :(得分:249)

您可以将复制构造函数设为私有,并且不提供任何实现:

private:
    SymbolIndexer(const SymbolIndexer&);

或者在C ++ 11中,明确禁止它:

SymbolIndexer(const SymbolIndexer&) = delete;

答案 1 :(得分:26)

如果你不介意多重继承(毕竟它并不是那么糟糕),你可以用私有拷贝构造函数和赋值运算符编写简单的类,并附加子类:

class NonAssignable {
private:
    NonAssignable(NonAssignable const&);
    NonAssignable& operator=(NonAssignable const&);
public:
    NonAssignable() {}
};

class SymbolIndexer: public Indexer, public NonAssignable {
};

对于GCC,这会给出以下错误消息:

test.h: In copy constructor ‘SymbolIndexer::SymbolIndexer(const SymbolIndexer&)’:
test.h: error: ‘NonAssignable::NonAssignable(const NonAssignable&)’ is private
但是,我不太确定这可以在每个编译器中工作。有一个related question,但尚无答案。

<强> UPD:

在C ++ 11中,您还可以编写NonAssignable类,如下所示:

class NonAssignable {
public:
    NonAssignable(NonAssignable const&) = delete;
    NonAssignable& operator=(NonAssignable const&) = delete;
    NonAssignable() {}
};

delete关键字阻止成员进行默认构造,因此不能在派生类的默认构造成员中进一步使用它们。尝试分配在GCC中给出以下错误:

test.cpp: error: use of deleted function
          ‘SymbolIndexer& SymbolIndexer::operator=(const SymbolIndexer&)’
test.cpp: note: ‘SymbolIndexer& SymbolIndexer::operator=(const SymbolIndexer&)’
          is implicitly deleted because the default definition would
          be ill-formed:

<强> UPD:

Boost已经有一个类只是出于同样的目的,我猜它甚至以类似的方式实现。该类名为boost::noncopyable,用于以下内容:

#include <boost/core/noncopyable.hpp>

class SymbolIndexer: public Indexer, private boost::noncopyable {
};

如果你的项目政策允许,我建议坚持使用Boost的解决方案。有关详细信息,另请参阅另一个boost::noncopyable-related question

答案 2 :(得分:4)

SymbolIndexer( const SymbolIndexer& )设为私有。如果您要分配参考,则不要复制。

答案 3 :(得分:-1)

了解引用与指针的 C++ 开发人员可能很想拥有

class MyClass {
    SomeClass acc;
public:
    MyClass() : acc() {}
    SomeClass &GetAccess( return acc; );
};

作为一种方便的方法:

someblock->{
    MyClass inst;
    auto acc = inst.GetAccess();  


    acc.SomeFunction();
}

这会在 SomeClass 内部产生双重释放的问题,因为默认情况下你最终会得到一个副本......