I have a bit of code that I find confusing. In particular, when I try to add something to a list as an initializer-list - it works until I add a destructor - then it starts trying to find a copy constructor.
This doesn't seem to be completely consistent behavior. Take this minimal example:
#include <list>
int main()
{
class MemberType
{
public:
MemberType() {}
MemberType(MemberType&& copy) { }
};
struct ListItemType
{
MemberType x;
~ListItemType() {}
};
std::list<ListItemType> myList;
myList.push_back({MemberType()});
return 0;
}
This fails to compile in GCC and VS2015 because the push_back
attempts to access the ListItemType
copy constructor:
main()::ListItemType::ListItemType(const main()::ListItemType&)
(as per my understanding). This seems to make some sense as the list push_back
will make a copy (since there is no move constructor), except this is not the behavior if you remove the destructor. Comment out the destructor and the compilation succeeds as expected.
That said, the following works fine even with the destructor - no copy or move constructors are needed to satisfy it. This seems like the same behavior to me though.
ListItemType foo = { MemberType() };
Finally, if you delete or comment out the move constructor of MemberType
- the compilation again succeeds - meaning the following will compile.
#include <list>
int main()
{
class MemberType
{
public:
MemberType() {}
};
struct ListItemType
{
MemberType x;
~ListItemType() {}
};
std::list<ListItemType> myList;
myList.push_back({MemberType()});
return 0;
}
Can someone please explain the behavior here? Why does the push_back
try to access the copy constructor of ListItemType
- but only if ListItemType
has a destructor and MemberType
has a move constructor?
Copy Constructor in C++ Copy constructor is used to initialize the members of a newly created object by copying the members of an already existing object. Copy constructor takes a reference to an object of the same class as an argument.
A user-defined copy constructor is generally needed when an object owns pointers or non-shareable references, such as to a file, in which case a destructor and an assignment operator should also be written (see Rule of three).
Which among the following is true for copy constructor? Explanation: It can't be defined with zero number of arguments. This is because to copy one object to another, the object must be mentioned so that compiler can take values from that object.
Default Copy Constructors: When a copy constructor is not defined, the C++ compiler automatically supplies with its self-generated constructor that copies the values of the object to the new object.
The behaviour you are observing is generated by the rules that govern whether implicit copy or move constructors are generated by the compiler:
If not defined, a move constructor is implicitly declared for a class if:
If not defined, a copy constructor is implicitly deleted for a class if:
In your question you have several cases:
ListItemType
has a destructorMemberType
has a move constructorThe implicit move constructor for ListItemType
has been deleted due to the existence of the destructor. Thus push_back
must use a copy constructor to place the ListItemType
into the list.
In that case, a copy constructor for ListItemType
cannot be implicitly declared as one of its data members (MemberType
) contains a move constructor, which prevents an implicit copy constructor for MemberType
being generated.
ListItemType
has no destructorMemberType
has a move constructorA move constructor can be implicitly generated for ListItemType
and used to move the value into the list.
ListItemType
has a destructorMemberType
has no move constructorAn implicit copy constructor for ListItemType
and MemberType
can be generated and used to copy the value into the list.
Finally, the expression ListItemType foo = { MemberType() };
is aggregate initialization and follows different rules. In either case MemberType
will have either a move or copy constructor that is sufficient for aggregate initialization.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With