0

I'm trying to understand what is meant by suppression of copy/move ctor/assignment. For instance in a cases where a class declares a destructor but does not declare move/copy ctor/assignment operations.

I originally was under the impression that these would simply not be generated (deleted) and compilation would fail. But after some experimentation this doesn't seem to be the case. However, if I explicitly mark the copy constructor as deleted then compilation does fail.

Note the snippet below was taken from 'The C++ Programming Language (4th edition)' Section 17.6.3.3. In the discussion that follows Stroustrup remarks:

"Also, Handle declares a destructor: this suppresses the generation of copy and move operations."

template< typename T >
class Handle {
    T *p;
  public:
    Handle( T *pp) : p{pp}{}

    T &operator*() {
      return *p;
    }

    // NOTE: I've added this method for testing.
    // this will cause compilation to fail, but commenting this
    // out does not fail compilation and g++ with -Wall emits no
    // warning
    Handle( const Handle &other ) = delete;

    ~Handle() {
      delete p;
    }
};

int
main( void ) {
  int x = 3;
  Handle< int >a( &x );
  Handle< int >b( a );
  return 0;
}

Compiled with g++ 6.3.0 with -std=c++11

So what exactly is meant by 'suppression' does it mean we don't get the corresponding methods generated unless some part of the code makes use of it? In other words, does having Handle< int >b( a ); override the 'suppression'?

stacker
  • 23
  • 3
  • 4
    Declaring a destructor does not prevent compiler from generating copy and move constructors, which is a source of woe for all programmers who don't follow [The Rule of Three/Five](https://stackoverflow.com/questions/4172722/what-is-the-rule-of-three). Check the rules of what is and what isn't generated by compiler [here](https://mariusbancila.ro/blog/2018/07/26/cpp-special-member-function-rules/) – Yksisarvinen May 14 '19 at 14:58
  • very related/possible duplicate: https://stackoverflow.com/questions/55813870/are-non-static-class-members-destroyed-even-without-a-destructor – NathanOliver May 14 '19 at 14:59
  • I personally prefer [the rule of *zero*](https://en.cppreference.com/w/cpp/language/rule_of_three#Rule_of_five). – Some programmer dude May 14 '19 at 15:02
  • For your example shown, in the destructor do you `delete` something that was allocated by `new`? – Some programmer dude May 14 '19 at 15:03
  • Lastly for your problem, I suggest you see e.g. [this copy-constructor reference](https://en.cppreference.com/w/cpp/language/copy_constructor) and [this move-constructor reference](https://en.cppreference.com/w/cpp/language/move_constructor). – Some programmer dude May 14 '19 at 15:05
  • @Yksisarvinen Declaring a (user-provided) destructor suppresses implicit generation of move constructor and move assignment operator. – Daniel Langr May 14 '19 at 15:09
  • @DanielLangr Yes, you are right. I forgot about that, sorry. – Yksisarvinen May 14 '19 at 15:11
  • @Someprogrammerdude no, we're allocating an int on the stack in main and passing the address of that to the constructor so we segfault at runtime. The point is I wasn't expecting this to compile at all given the user supplied destructor – stacker May 16 '19 at 14:17
  • @Yksisarvinen Quoting the section on the rule of 3 from the link you provided in your first post: 'If you need to explicitly declare either the destructor, copy constructor or copy assignment operator yourself, you probably need to explicitly declare all three of them.' But as noted in my original post, supplying the destructor suppresses the other member functions. So how is it that Handle< int >b( a ); in my example doesn't cause the compilation to fail (reminder you can comment out the line that declares the copy constructor as deleted and compilation will succeed)? – stacker May 16 '19 at 14:20
  • @Someprogrammerdude Thanks for the links on copy constructor and move constructor. If I understood correctly, the move constructor should be marked as deleted since a) there is a user defined constructor and b) int * is non-static and does not define a move constructor (is this correct?) . For the copy constructor on the other hand its generation is 'deprecated' if there is a user supplied destructor, so I guess this is why compilation doesn't fail. The compiler still generates the copy constructor despite it being deprecated behavior. – stacker May 16 '19 at 14:52

0 Answers0