C++ boost::noncopyable 的优点是什么

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7823990/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 17:32:58  来源:igfitidea点击:

What are the advantages of boost::noncopyable

c++boostnoncopyable

提问by tenfour

To prevent copying a class, you can very easily declare a private copy constructor / assignment operators. But you can also inherit boost::noncopyable.

为了防止复制一个类,你可以很容易地声明一个私有的复制构造函数/赋值运算符。但是你也可以继承boost::noncopyable.

What are the advantages / disadvantages of using boost in this case?

在这种情况下使用 boost 的优点/缺点是什么?

采纳答案by tenfour

Summarizing what others have said:

总结一下别人说的:

Advantages of boost::noncopyableover private copy methods:

boost::noncopyable优于私有复制方法的优点

  1. It is more explicit and descriptive in the intent. Using private copy functions is an idiom that takes longer to spot than noncopyable.
  2. It is less code / less typing / less clutter / less room for error (the easiest would be accidentally providing an implementation).
  3. It embeds meaning right in the type's metadata, similar to a C# attribute. You can now write a function which accepts only objects which are noncopyable.
  4. It potentially catches errors earlier in the build process. The error will be presented at compile-time rather than link-time, in the case that the class itself or friends of the class are doing the erroneous copying.
  5. (almost the same as #4) Prevents the class itself or friends of the class from calling the private copy methods.
  1. 它在意图中更加明确和描述性。使用私有复制函数是一种习惯用法,它比noncopyable.
  2. 它是更少的代码/更少的输入/更少的混乱/更少的错误空间(最简单的方法是意外提供一个实现)。
  3. 它在类型的元数据中嵌入了含义,类似于 C# 属性。您现在可以编写一个仅接受不可复制对象的函数。
  4. 它可能会在构建过程的早期捕获错误。错误将在编译时而不是链接时出现,以防类本身或类的朋友正在执行错误的复制。
  5. (几乎与#4 相同)防止类本身或类的朋友调用私有复制方法。

Advantages of private copy methods over boost::noncopyable:

私有复制方法的优势在于boost::noncopyable

  1. No boost dependency
  1. 没有增强依赖

回答by Howard Hinnant

I see no documentation benefit:

我看不到文档方面的好处:

#include <boost/noncopyable.hpp>

struct A
    : private boost::noncopyable
{
};

vs:

对比:

struct A
{
     A(const A&) = delete;
     A& operator=(const A&) = delete;
};

When you add move-only types, I even see the documentation as misleading. The following two examples are not copyable, though they are movable:

当您添加仅移动类型时,我什至认为文档具有误导性。以下两个示例是不可复制的,但它们是可移动的:

#include <boost/noncopyable.hpp>

struct A
    : private boost::noncopyable
{
    A(A&&) = default;
    A& operator=(A&&) = default;
};

vs:

对比:

struct A
{
    A(A&&) = default;
    A& operator=(A&&) = default;
};

Under multiple inheritance, there can even be a space penalty:

在多重继承下,甚至会有空间损失:

#include <boost/noncopyable.hpp>

struct A
    : private boost::noncopyable
{
};

struct B
    : public A
{
    B();
    B(const B&);
    B& operator=(const B&);
};

struct C
    : public A
{
};

struct D
    : public B,
      public C,
      private boost::noncopyable
{
};

#include <iostream>

int main()
{
    std::cout << sizeof(D) << '\n';
}

For me this prints out:

对我来说,这会打印出来:

3

But this, which I believe to have superior documentation:

但是,我相信它具有出色的文档:

struct A
{
    A(const A&) = delete;
    A& operator=(const A&) = delete;
};

struct B
    : public A
{
    B();
    B(const B&);
    B& operator=(const B&);
};

struct C
    : public A
{
    C(const C&) = delete;
    C& operator=(const C&) = delete;
};

struct D
    : public B,
      public C
{
    D(const D&) = delete;
    D& operator=(const D&) = delete;
};

#include <iostream>

int main()
{
    std::cout << sizeof(D) << '\n';
}

Outputs:

输出:

2

I find it much easier to declare my copy operations than to reason whether or not I'm deriving from boost::non_copyablemultiple times and if that is going to cost me. Especially if I'm not the author of the complete inheritance hierarchy.

我发现声明我的复制操作比推理我是否boost::non_copyable多次派生以及这是否会花费我要容易得多。特别是如果我不是完整继承层次结构的作者。

回答by Nawaz

It makes the intent explicit and clear, otherwise one has to see the definition of the class,and search for the declaration related to copy-semantic, and then look for the access-specifier in which it is declared, in order to determine whether the class is noncopyable or not. Other way to discover it by writing code that requires copy-semantic enabled and see the compilation error.

它使意图明确明确,否则必须查看类的定义,并搜索与复制语义相关的声明,然后查找声明它的访问说明符,以确定是否类是否不可复制。通过编写需要启用复制语义的代码并查看编译错误来发现它的其他方法。

回答by thiton

  1. The intent of boost::noncopyable is clearer.
  2. Boost::noncopyable prevents the classes methods from accidentally using the private copy constructor.
  3. Less code with boost::noncopyable.
  1. boost::noncopyable 的意图更清晰。
  2. Boost::noncopyable 防止类方法意外使用私有复制构造函数。
  3. 使用 boost::noncopyable 减少代码。

回答by ansgri

I can't understand why no one else seem to mention it, but:

我不明白为什么其他人似乎没有提到它,但是:

With noncopyableyou write the name of your class just once.

随着noncopyable你写你的类的名称一次。

Without, fivefold duplication: One A for 'class A', two to disable the assignment, and two to disable the copy constructor.

没有,五重重复:一个 A 代表“类 A”,两个禁用赋值,两个禁用复制构造函数。

回答by Viktor Sehr

Quoting the documentation:

引用文档:

"The traditional way to deal with these is to declare a private copy constructor and copy assignment, and then document why this is done. But deriving from noncopyable is simpler and clearer, and doesn't require additional documentation."

“处理这些问题的传统方法是声明一个私有复制构造函数和复制赋值,然后记录为什么要这样做。但从 noncopyable 派生更简单、更清晰,不需要额外的文档。”

http://www.boost.org/libs/utility/utility.htm#Class_noncopyable

http://www.boost.org/libs/utility/utility.htm#Class_noncopyable

回答by Mike Seymour

One concrete advantage (beyond expressing your intent slightly more clearly) is that the error will be caught sooner, at the compile stage not the link stage, if a member or friend function tries to copy an object. The base-class constructor/assignment are not accessible anywhere, giving a compile error.

一个具体的优点(除了稍微更清楚地表达您的意图之外)是,如果成员或友元函数试图复制对象,则在编译阶段而不是链接阶段会更快地捕获错误。无法在任何地方访问基类构造函数/赋值,从而导致编译错误。

It also prevents you accidentally defining the functions (i.e. typing {}instead of ;), a small error which may well go unnoticed, but which would then allow members and friends to make invalid copies of the object.

它还可以防止您意外地定义函数(即键入{}而不是;),这是一个很可能被忽视的小错误,但它会允许成员和朋友制作对象的无效副本。

回答by Nikko

The advantage is that you don't have to write a private copy constructor and a private copy operator yourself and it expresses clearly your intention without writing additional documentation.

优点是您不必自己编写私有复制构造函数和私有复制运算符,并且无需编写额外的文档即可清楚地表达您的意图。

回答by manlio

A smalldisadvantage (GCC specific) is that, if you compile your program with g++ -Weffc++and you have classes containing pointers, e.g.

一个小的缺点(特定于 GCC)是,如果你编译你的程序g++ -Weffc++并且你有包含指针的类,例如

class C : boost::noncopyable
{
public:
  C() : p(nullptr) {}

private:
  int *p;
};

GCC doesn't understand what's happening:

GCC 不明白发生了什么:

warning: 'class C' has pointer data members [-Weffc++]
warning: but does not override 'C(const S&)' [-Weffc++]
warning: or 'operator=(const C&)' [-Weffc++]

警告:“C 类”具有指针数据成员 [-Weffc++]
警告:但不覆盖“C(const S&)”[-Weffc++]
警告:或“operator=(const C&)”[-Weffc++]

While it won't complain with:

虽然它不会抱怨:

#define DISALLOW_COPY_AND_ASSIGN(Class) \
  Class(const Class &) = delete;     \
  Class &operator=(const Class &) = delete

class C
{
public:
  C() : p(nullptr) {}
  DISALLOW_COPY_AND_ASSIGN(C);

private:
  int *p;
};

PS I know GCC's -Weffc++ has several issues. The code that checks for "problems" is pretty simplicistic, anyway... sometimes it helps.

PS 我知道 GCC 的 -Weffc++ 有几个问题。无论如何,检查“问题”的代码非常简单……有时它会有所帮助。

回答by wjl

I'd rather use boost::noncopyable than manually delete or privatize the copy constructor and assignment operator.

我宁愿使用 boost::noncopyable 而不是手动删除或私有化复制构造函数和赋值运算符。

However, I almost never use eithermethod, because:

但是,我几乎从不使用任何一种方法,因为:

If I am making a non-copyable object, there has to be a reason it is non-copyable. This reason, 99% of the time, is because I have members that can't be copied meaningfully. Chances are, such members would also be better suited as private implementation details. So I make most such classes like this:

如果我正在制作一个不可复制的对象,则必须有一个不可复制的原因。这个原因,在 99% 的情况下,是因为我的成员无法被有意义地复制。很有可能,这些成员也更适合作为私有实现细节。所以我制作了大多数这样的课程:

struct Whatever {
  Whatever();
  ~Whatever();
  private:
  struct Detail;
  std::unique_ptr<Detail> detail;
};

So now, I have a private implementation struct, and since I've used std::unique_ptr, my top-level class is non-copyable for free. The link errors that come from this are understandable because they talk about how you can't copy a std::unique_ptr. To me, this is all the benefits of boost::noncopyable and a private implementation rolled into one.

所以现在,我有一个私有实现结构,并且由于我使用了 std::unique_ptr,因此我的顶级类是不可免费复制的。由此产生的链接错误是可以理解的,因为它们讨论了如何无法复制 std::unique_ptr。对我来说,这就是 boost::noncopyable 和私有实现合二为一的所有好处。

The benefit with this pattern is later, if I decide that I did indeed want to make my objects of this class copyable, I can just add and implement a copy constructor and/or assignment operator without changing the class hierarchy.

这种模式的好处是后来,如果我决定我确实想让我的这个类的对象可复制,我可以只添加和实现一个复制构造函数和/或赋值运算符,而无需更改类层次结构。