Menu

What is the point of noExplicitCopyMoveConstructor?

2015-11-05
2015-11-13
  • Kazutoshi Satoda

    The error noExplicitCopyMoveConstructor says:
    https://github.com/danmar/cppcheck/blob/a5f577d179e09e436b544bcbbb6b798a47f6c8b6/lib/checkclass.cpp#L778

    Abstract class 'CLASSNAME' has a copy/move constructor that is not explicit.
    For abstract classes, even copy/move constructors may be declared explicit,
    as, by definition, abstract classes cannot be instantiated, and so objects of
    such type should never be passed by value.

    Could you please give an example of the problem which is solved by
    adding "explicit" as suggested by noExplicitCopyMoveConstructor?

    This message suggests fixes like this:

     class Abstract {
     public:
       virtual void f() = 0;
    -  Abstract(Abstract const&);
    +  explicit Abstract(Abstract const&);
     }
    

    But I can't see any improvement by this change.

    The message seems saying that the "explicit" avoids accidental pass by
    value of an abstract class. But declaring a parameter with abstract class
    is an error by itself, regardless the explicit-ness of its copy/move
    constructor.

    $ cat test.cpp
    struct Abstract { virtual void f() = 0; };
    void x(Abstract a);
    $ g++ test.cpp -fsyntax-only
    test.cpp:2:17: error: cannot declare parameter 'a' to be of abstract type 'Abstract'
     void x(Abstract a);
                     ^
    test.cpp:1:8: note:   because the following virtual functions are pure within 'Abstract':
     struct Abstract { virtual void f() = 0; };
            ^
    test.cpp:1:32: note:    virtual void Abstract::f()
     struct Abstract { virtual void f() = 0; };
                                ^
    

    Moreover, non-explicit copy/move constructor is implicitly declared if
    not declared by user.
    http://en.cppreference.com/w/cpp/language/copy_constructor

    If no user-defined copy constructors are provided for a class type
    (struct, class, or union), the compiler will always declare a copy
    constructor as a non-explicit inline public member of its class.

    Then, if non-explicit copy/move constructor is really dangerous, I think
    it is odd that the error is produced only for user declared case.

     
  • Daniel Marjamäki

    Yes I agree, I can't personally see why explicit should be used. I'll forward this question..

     
  • Daniel Marjamäki

    I got answer:

    Hello!

    The answer is, that even constructors of abstract classes can be mistakenly used in conversion, but only in C++11 norm (or newer). Please see following code, which can be compiled in GCC with C++11 support:

    struct A
    {
        A(int size) { }
        virtual void f() = 0;
    };
    
    struct B : public A
    {
        using A::A; // need C++11
    
        virtual void f() override {}
    };
    
    void myFunc(B instance)
    {
    }
    
    int main()
    {
      B object(5);  // This compiles, it is dangerous
      B nextObject = 5; // This compiles also
    
      myFunc(5); // Very dangerous
    }
    

    Here is the problem that 5 can be casted to B type, which can be considered as dangerous. I can also pass 5 as argument to function myFunc, which can be considered as dangerous.

    Best regards,
    Jakub Melka

     
    • Kazutoshi Satoda

      The answer is, that even constructors of abstract classes can be
      mistakenly used in conversion, but only in C++11 norm (or newer). ...

      The given example shows just the danger of a non-explicit constructor.
      It could be an answer for noExplicitConstructor. But it is not an answer
      for my question about noExplicitCopyMoveConstructor.

       
  • Daniel Marjamäki

    So.. maybe we should only write this warning in C++11.

     
  • Daniel Marjamäki

    I will remove this noExplicitCopyMoveConstructor.

    If somebody can see a good reason to have it we can readd it.

    Thanks!

     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.