boost :: noncopyable有什么优点

ten*_*our 64 c++ boost noncopyable

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

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

How*_*ant 47

我看不到文档的好处:

#include <boost/noncopyable.hpp>

struct A
    : private boost::noncopyable
{
};
Run Code Online (Sandbox Code Playgroud)

VS:

struct A
{
     A(const A&) = delete;
     A& operator=(const A&) = delete;
};
Run Code Online (Sandbox Code Playgroud)

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

#include <boost/noncopyable.hpp>

struct A
    : private boost::noncopyable
{
    A(A&&) = default;
    A& operator=(A&&) = default;
};
Run Code Online (Sandbox Code Playgroud)

VS:

struct A
{
    A(A&&) = default;
    A& operator=(A&&) = default;
};
Run Code Online (Sandbox Code Playgroud)

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

#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';
}
Run Code Online (Sandbox Code Playgroud)

对我来说这打印出来:

3
Run Code Online (Sandbox Code Playgroud)

但是,我认为这有更好的文档:

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';
}
Run Code Online (Sandbox Code Playgroud)

输出:

2
Run Code Online (Sandbox Code Playgroud)

我发现声明我的复制操作要比判断我是否boost::non_copyable多次派生以及是否会让我付出代价要容易得多.特别是如果我不是完整继承层次结构的作者.

  • 公平地说,`boost :: noncopyable`早在C++ 11之前就已经可用,并且编译支持`= delete`.我同意你的看法,对于C++ 11近乎兼容的编译器,它现在已经过时了. (24认同)
  • 有人有一个好主意,并使`noncopyable`成为CRTP基类,因此层次结构中的所有基类都是唯一的. (6认同)
  • 另一个缺点是`private:__ copy_constructor __;`是完全可移植的,你不需要~40 MB的Boost依赖项. (3认同)
  • 这提出了一个问题:C++ 11中还有哪些提升功能已经过时了? (2认同)
  • @Jon:这个问题没有硬性和快速的答案.然而(仅作为一个例子)我会考虑在到达'boost :: ptr_vector <animal>之前使用`std :: vector <std :: unique_ptr <animal >>`(http://www.boost.org/doc) /libs/1_54_0/libs/ptr_container/doc/tutorial.html).理由:如果我知道`vector`,并且我知道`unique_ptr`,那么我就知道unique_ptr的向量的语义.我知道std :: algorithms(例如sort)如何与它交互.我不必学习有关其成员算法的新容器(例如成员排序). (2认同)

Naw*_*waz 42

它使得intent 明确而清晰,否则必须看到类的定义,并搜索与copy-semantic相关的声明,然后查找声明它的access-specifier,以确定是否class是不可复制的.通过编写需要启用了复制语义的代码来发现它的其他方法,并查看编译错误.

  • @spraff:这被称为类的*definition*.类的**定义*包含所有*声明的*成员. (7认同)
  • @spraff:我不明白你的意思*技术*差异.我说过那种吗? (5认同)
  • 您不必在定义中看到复制运算符在声明中是私有的. (4认同)
  • 如果您无法访问类定义,那么它是一个不完整的类型,您无法真正将其用于*任何*.没有这个定义,你也看不到它继承了`noncopyable`.所以这是一个有争议的问题. (3认同)

ten*_*our 41

总结别人说的话:

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

  1. 它在意图中更明确,更具描述性.使用私人复制功能是一种需要更长时间才能发现的习惯用法noncopyable.
  2. 它更少的代码/更少的打字/更少的混乱/更少的错误空间(最容易意外提供实现).
  3. 它在类型的元数据中嵌入了意义,类似于C#属性.您现在可以编写一个只接受不可复制对象的函数.
  4. 它可能在构建过程的早期捕获错误.在类本身或类的朋友正在进行错误复制的情况下,错误将在编译时而不是链接时呈现.
  5. (与#4几乎相同)防止类本身或类的朋友调用私有复制方法.

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

  1. 没有提升依赖性

  • 正如@Howard Hinnant所指出的,还存在空间劣势 (10认同)

thi*_*ton 16

  1. boost :: noncopyable的意图更清晰.
  2. Boost :: noncopyable可防止类方法意外使用私有拷贝构造函数.
  3. 使用boost :: noncopyable减少代码.


ans*_*gri 16

我无法理解为什么没有其他人似乎提到它,但是:

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

没有,五倍重复:一个用于'A类',两个用于禁用赋值,两个用于禁用复制构造函数.


Vik*_*ehr 9

引用文档:

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

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


Mik*_*our 8

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

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