What are the advantages of boost::noncopyable

前端 未结 11 1160
野性不改
野性不改 2020-11-27 14:10

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

相关标签:
11条回答
  • 2020-11-27 14:12

    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.

    0 讨论(0)
  • 2020-11-27 14:17

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

    0 讨论(0)
  • 2020-11-27 14:22

    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.

    0 讨论(0)
  • 2020-11-27 14:22

    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.

    0 讨论(0)
  • 2020-11-27 14:23

    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.

    0 讨论(0)
  • 2020-11-27 14:25

    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

    0 讨论(0)
提交回复
热议问题