Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

implicit vs. explicit deleted copy constructor

Tags:

c++

c++11

I've recently experienced some strange behaviour in my C++11 code.

I've got a class, which is only movable:

class only_move
{
public:

    only_move() :  value(0) {}

    only_move(int value) : value(value) {}

    only_move(const only_move&) = delete;
    only_move& operator=(const only_move&) = delete;

    only_move(only_move&&) = default;
    only_move& operator=(only_move&&) = default;

    int value;
};

And I've got another class, which contains an only_move object:

class has_only_move_member
{
public:

    has_only_move_member() = delete;

    has_only_move_member(only_move&& value) : member(std::move(value)) {}

    only_move member;
};

If I understood it correct, that means has_only_move_member can't be copied, as the only_move member can't be copied. This means has_only_move_member(const has_only_move_member&) is deleted implicitly. Let's check that out:

has_only_move_member object(only_move(5));
has_only_move_member copy_of_object(object);

As expected, it prints out:

error: use of deleted function ‘has_only_move_member::has_only_move_member(const has_only_move_member&)’
note: ‘has_only_move_member::has_only_move_member(const has_only_move_member&)’ is implicitly deleted because the default definition would be ill-formed:
class has_only_move_member

Okay, so I moved on and put has_only_move_member instances in a std::map. As they don't have a copy constructor, I've moved them into it:

has_only_move_member object(only_move(5));

std::map<int, has_only_move_member> data;
data.emplace(5, std::move(object));

So far so good. This works like a charm.

But I had an idea. What about being more explicit and explicitly deleting the copy constructor of has_only_move_member. So I wrote into the class has_only_move_member:

has_only_move_member(const has_only_move_member&) = delete;

After that, the same code from above, there I moved objects into an map gives me an error:

/usr/include/c++/4.8/bits/stl_pair.h:134:45: error: use of deleted function ‘has_only_move_member::has_only_move_member(const has_only_move_member&)’

Yeah of course it's deleted, but why is there such a gap between implicit and explicit delete?

I'm getting the same behaviour with g++ 4.8.2 and clang 3.4-rc1 on Debian with libstdc++ and recent apple-clang-llvm 4.0 on Mac OS X 10.9 with libc++

like image 410
Mario Avatar asked Dec 02 '13 12:12

Mario


People also ask

What is implicit copy constructor?

An implicitly defined copy constructor will copy the bases and members of an object in the same order that a constructor would initialize the bases and members of the object.

What is deleted copy constructor?

The copy constructor and copy-assignment operator are public but deleted. It is a compile-time error to define or call a deleted function. The intent is clear to anyone who understands =default and =delete . You don't have to understand the rules for automatic generation of special member functions.

When should you delete copy constructor?

When to delete copy constructor and assignment operator? Copy constructor (and assignment) should be defined when ever the implicitly generated one violates any class invariant. It should be defined as deleted when it cannot be written in a way that wouldn't have undesirable or surprising behaviour.

What are the types of copy constructor?

Copy Constructor is of two types:Default Copy constructor: The compiler defines the default copy constructor. If the user defines no copy constructor, compiler supplies its constructor. User Defined constructor: The programmer defines the user-defined constructor.


1 Answers

I already said this in the comment but since this is a correct answer I am reposting as one:

You added a custom constructor (even though it's a deleted one). Therefore the compiler won't auto generate a move constructor. The compiler then falls back to copying which (as you requested) it obviously can't do.

like image 138
John5342 Avatar answered Sep 23 '22 16:09

John5342