boost::noncopyable 的优点是什么

发布于 2024-12-10 19:08:14 字数 112 浏览 5 评论 0原文

为了防止复制类,您可以非常轻松地声明私有复制构造函数/赋值运算符。但您也可以继承boost::noncopyable

在这种情况下使用 boost 有哪些优点/缺点?

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

守护在此方 2024-12-17 19:08:14

我没有看到任何文档优势:

#include <boost/noncopyable.hpp>

struct A
    : private boost::noncopyable
{
};

vs:

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

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

#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;
};

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

#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';
}

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

3

但是,我相信它有更好的文档:

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';
}

输出:

2

我发现它很多声明我的复制操作比推理我是否多次从 boost::non_copyable 派生以及这是否会让我付出代价更容易。特别是如果我不是完整继承层次结构的作者。

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_copyable multiple times and if that is going to cost me. Especially if I'm not the author of the complete inheritance hierarchy.

魂ガ小子 2024-12-17 19:08:14

总结一下其他人所说的:

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

  1. 它的意图更加明确和描述性。使用私有复制函数是一种比 noncopyable 更难发现的习惯用法。
  2. 它是更少的代码/更少的打字/更少的混乱/更少的错误空间(最简单的是意外地提供一个实现)。
  3. 它将含义直接嵌入到类型的元数据中,类似于 C# 属性。您现在可以编写一个仅接受不可复制对象的函数。
  4. 它有可能在构建过程的早期捕获错误。如果类本身或类的朋友进行了错误的复制,则错误将在编译时而不是链接时出现。
  5. (几乎与 #4 相同)防止类本身或类的朋友调用私有复制方法。

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

  1. 无 boost 依赖

Summarizing what others have said:

Advantages of boost::noncopyable over private copy methods:

  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.

Advantages of private copy methods over boost::noncopyable:

  1. No boost dependency
GRAY°灰色天空 2024-12-17 19:08:14

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

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.

旧城空念 2024-12-17 19:08:14
  1. boost::noncopyable 的意图更加清晰。
  2. Boost::noncopyable 可防止类方法意外使用私有复制构造函数。
  3. 使用 boost::noncopyable 减少代码。
  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.
画离情绘悲伤 2024-12-17 19:08:14

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

使用 noncopyable 你只需写一次类的名称。

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

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

With noncopyable you write the name of your class just once.

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

寂寞清仓 2024-12-17 19:08:14

引用文档:

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

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

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."

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

过气美图社 2024-12-17 19:08:14

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

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

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.

甜`诱少女 2024-12-17 19:08:14

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

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

private:
  int *p;
};

GCC无法理解发生了什么:

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

虽然它不会抱怨:

#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 我知道 GCC 的 -Weffc++ 有几个问题。无论如何,检查“问题”的代码非常简单......有时它会有所帮助。

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

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

private:
  int *p;
};

GCC doesn't understand what's happening:

warning: 'class C' has pointer data members [-Weffc++]
warning: but does not override 'C(const S&)' [-Weffc++]
warning: or '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.

一场信仰旅途 2024-12-17 19:08:14

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

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.

柠檬心 2024-12-17 19:08:14

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

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

如果我正在创建一个不可复制的对象,那么它是不可复制的就必须有一个原因。这个原因,99%的情况,是因为我有无法有意义复制的成员。有可能,此类成员也更适合作为私有实施细节。所以我制作大多数这样的类:

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

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

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

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

However, I almost never use either method, 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:

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.

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.

温柔少女心 2024-12-17 19:08:14

缺点,根据斯科特·迈耶斯的说法,如果你确实需要找到它的缺点的话,这个名字是“非自然的”。

The disavantage, according to Scott Meyers, the name is "non-natrual", if you do need to find a disavantage of it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文