简体   繁体   English

boost :: noncopyable如何工作

[英]How does boost::noncopyable work

I've stumbled upon 2 stupid questions during my C++ practixe : 在我的C ++实践中,我偶然发现了两个愚蠢的问题:

  1. AFAIK in c++ copy constructor and assignment operators are not inherited...so how does boost::noncopyable help in this case to prohibit this stuff? c ++拷贝构造函数和赋值运算符中的AFAIK不是继承的......那么在这种情况下boost :: noncopyable如何帮助禁止这些东西呢?

    \nclass X: private boost::noncopyable class X:private boost :: noncopyable\n{ {\n}; };\n
    Is it necessary to use only private inheritance to achieve the goal? 是否有必要仅使用私有继承来实现目标?

  2. Is there only 1 way to declare assignment operator 是否只有一种方法来声明赋值运算符

    \nMyClass& operator= ( const MyClass & ); MyClass&operator =(const MyClass&);\n
    Is it the same thing to declare 申报是否同样如此
    \nvoid operator= ( const MyClass & ); void operator =(const MyClass&); 
    or 要么
    \nconst MyClass& operator= ( const MyClass & ); const MyClass&operator =(const MyClass&); 
    ?

You are correct that the copy constructor and copy assignment operator are not inherited. 您是正确的,不会继承复制构造函数和复制赋值运算符。 Fortunately we do not need them inherited in order for this to work. 幸运的是,我们不需要继承它们才能使其工作。 If you inherit from a class that cannot be copied then that derived class cannot be copied as well as it cannot call the base class copy constructor in it's copy constructor. 如果继承自无法复制的类,则无法复制该派生类,也无法在其复制构造函数中调用基类复制构造函数。

Essential you inherit from a class that looks like 你必须从一个看起来像的类继承

struct NonCopyable {
    NonCopyable & operator=(const NonCopyable&) = delete;
    NonCopyable(const NonCopyable&) = delete;
    NonCopyable() = default;
};

Which is enough to stop the compiler generated copy and assignment in the derived class from working. 这足以阻止编译器在派生类中生成的副本和赋值工作。 You can provide your own and override this but then that is defeating the point. 你可以提供自己的并覆盖它,但那就是打败了这一点。

The non-copyable in C++11 and later will work by declaring it =delete , preferably public. C ++ 11及更高版本中的不可复制将通过声明它=delete ,最好是公共的。 However, before C++11 this was not possible and the combination of 2 techniques are being used: 但是,在C ++ 11之前,这是不可能的,并且正在使用2种技术的组合:

  • Declare the method private 声明方法是私有的
  • Don't implement the method 不要实现该方法

By making the method private, this cannot be called by non-friend classes. 通过将该方法设为私有,非友元类不能调用此方法。 As a result, any code trying to call this will result in a compilation error. 因此,任何试图调用此代码的代码都将导致编译错误。

In practice, the class can still copy itself. 在实践中,该类仍然可以自我复制。 Therefore this method does not get implemented and you will get a linker error. 因此,此方法未实现,您将收到链接器错误。

Inheriting from boost::noncopyable will prevent the second use case, however, it also prevents that the compiler can generate a valid default copy constructor ... as they will violate the previous constraints. boost::noncopyable继承将阻止第二个用例,但是,它也会阻止编译器生成有效的默认复制构造函数......因为它们将违反先前的约束。

Note that if you really want, you can write copy constructors for the inheriting class by calling the normal constructors of these 'non-copyable' classes. 请注意,如果您确实需要,可以通过调用这些“不可复制”类的常规构造函数来为继承类编写复制构造函数。

For your second question: Yes, you can give it whatever return type you want, though you can't write a = b = c; 对于你的第二个问题:是的,你可以给它任何你想要的返回类型,尽管你不能写a = b = c; anymore. 了。

1) When an object is constructed, all of the member objects and base objects must also be constructed. 1)构造对象时,还必须构造所有成员对象和基础对象。 Since noncopyable::noncopyable(const noncopyable &) is private, noncopyable can never be copy-constructed. 由于noncopyable::noncopyable(const noncopyable &)是私有的,因此不能复制构造noncopyable Therefore, any object that contains it as a member or base can also never be copy-constructed. 因此,任何包含它作为成员或基础的对象也不能复制构造。

2) You may declare you assignment operator any of the three ways you've described. 2)您可以通过您描述的三种方式中的任何一种声明赋值运算符。 No, they are not "the same thing". 不,他们不是“同一件事”。 One returns a mutable reference, one returns a const reference, and one returns void. 一个返回一个可变引用,一个返回一个const引用,一个返回void。 The difference will be apparent if you ever try to operate on the result of the assignment operator. 如果您尝试操作赋值运算符的结果,则差异将很明显。 Consider this program fragment: 考虑这个程序片段:

a = b;
(a = b).foo()

The first line will operate the same with any of your assignment operators. 第一行将与任何赋值运算符一样运行。 The second line will vary according to which assignment operator you use. 第二行将根据您使用的赋值运算符而有所不同。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM