Why is this code trying to call the copy constructor? - c++

I just spent an inordinate amount of time fiddling with a complilation error in Visual Studio. I have distilled the code into the small compilable example below and tried it on IdeOne and got the same error which you can see here.
I am wondering why the following code tries to call B(const B&) instead of B(B&&):
#include <iostream>
using namespace std;
class A {
public:
A() : data(53) { }
A(A&& dying) : data(dying.data) { dying.data = 0; }
int data;
private:
// not implemented, this is a noncopyable class
A(const A&);
A& operator=(const A&);
};
class B : public A { };
int main() {
B binst;
char* buf = new char[sizeof(B)];
B* bptr = new (buf) B(std::move(binst));
cout << bptr->data << endl;
delete[] buf;
}
I didn't explicitly define any constructors, so B(std::move(binst)) should call the compiler generated B(B&&), no?
When I change B to
class B : public A {
public:
B() { }
B(B&&) { }
};
It compiles fine. Why is this?
It will be extremely inconvenient if this can't be fixed from the base class because I have a template class which uses placement new and move constructors like the example, and it will require every class that is not copyable (which is not and definitely should not be a requirement for use with my template class) to have an explicitly defined move constructor.

If you are using Visual Studio 2010 or 2012, be advised: the compiler does not automatically generate move constructors for you. That wasn't implemented. So you need to write them yourself.

You must be facing a compiler bug. The standard says that B gets an implicitly declared and defined move constructor; all the conditions of 12.8(9) are met (i.e. B does not have an explicitly declared copy constructor, copy-assignment, etc, and the move constructor would not implicitly be declared deleted).

Related

the usage of copy-constructor method?

In my code, I used inner-class as an iterator for another class.
To simplify the situation, the code can be shown as follows:
class A {
public:
class B {
public:
explicit B(void):idx(3){}
B(const B&b) {
idx = 4; // never be called
}
private:
int idx=0;
};
B getB()
{ return A::B(); }
};
void test2(){
A a;
A::B b = a.getB(); // b.idx ends with value of 3
}
The problem is that, in test2() , while running A::B b = a.getB();, the copy-constructor method wasn't called. And the b ends with value 3.
Why is this?
For another problem confused me
class A {
public:
class B {
public:
explicit B(void):idx(3){}
explicit B(const B&b) {} // C2440, cannot convert from "A::B" to "A::B"
private:
int idx=0;
};
B getB()
{ return A::B(); }
};
Why will C2440 ocurrs with two types exactly the same?
What you are seeing is copy elision. In order to make it easier for optimizers to speed up the generated code, the C++ standard allows copy constructors to be skipped in certain situations.
C++ language does not guarantee the side effects of copy (nor of move) constructors to be observable in the abstract machine. This non-guarantee lets the compiler avoid temporary objects when they are not necessary, thereby avoiding copying of those objects in the concrete machine.
Your program relies on the side effects of a copy constructor. This is bad; Don't do it.

Why does gcc warn about calling a non-trivial move assignment operator with std::tuple and virtual inheritance?

In the following example gcc 7 gives a warning:
defaulted move assignment for 'B' calls a non-trivial move assignment
operator for virtual base 'A' [-Wvirtual-move-assign]
if I create an std::tuple<B> object. Clang 5 doesn't report any problems. Also the problem goes away if vector is removed from Base. Example.
#include <tuple>
#include <vector>
class Base
{
public:
virtual ~Base();
std::vector<int> v;
};
class A : public Base
{
};
class B : public virtual A
{
};
int main()
{
B *b = new B;
B another{*b}; // <<<--- this compiles
std::tuple<B> t; // <<<--- gives warning
}
Why does it happen in presence of std::tuple (and absence of move assignment) and what is the proper way to fix it if I need to keep such a hierarchy?
The warning is unrelated to tuple, it is triggered by a move assignment of B. For instance, the following code generates the warning
B b;
B t;
t = std::move(b);
The gcc documentation explains the intent of the warning
-Wno-virtual-move-assign
Suppress warnings about inheriting from a virtual base with a non-trivial C++11 move assignment operator. This is dangerous because if the virtual base is reachable along more than one path, it is moved multiple times, which can mean both objects end up in the moved-from state. If the move assignment operator is written to avoid moving from a moved-from object, this warning can be disabled.
Here's an example that demonstrates the problem
struct Base
{
Base() = default;
Base& operator=(Base&&)
{
std::cout << __PRETTY_FUNCTION__ << '\n';
return *this;
}
};
struct A : virtual Base {};
struct B : virtual Base {};
struct C : A, B {};
int main()
{
C c;
c = C();
}
This produces the output
Base& Base::operator=(Base&&)
Base& Base::operator=(Base&&)
showing that the single Base instance was moved assigned to twice, once by each move assignment operator of A and B. The second move assignment is from an already moved from object, which could cause the contents from the first move assignment to be overwritten.
Note that clang also generates a warning in my example, it's probably detecting that A is not reachable via two paths in your example and not emitting the warning.
The way to fix it is to implement move assignment operators for A and B that can detect that Base has been moved from and omit a second move assignment.

Factory requires only declaration of copy ctor without implementation

I'm experiencing behavior which I don't understand in a copy constructor of derived class.
class A {
A(const A&);
public:
A() = default;
};
class B : public A {
friend class Factory;
B(const int v) : A(), m_test_val(v) {}
public:
int m_test_val;
B(const B&); // no implementation, just declaration
};
class Factory {
public:
static B create(const int v) {
return B(v);
}
};
int main() {
B b = Factory::create(2);
std::cout << b.m_test_val << '\n';
return 0;
}
The behavior I don't understand is a matter of a working copy constructor B::B(const B&); which, however, does not have any implementation.
When I use B::B(const B&) = default; instead, I get an error saying I'm using deleted function (implicitly deleted because of ill-formation) in the return statement of the Factory::create() function (The A::A(const A&) is private and without implementation on purpose).
And of course, when I use B::B(const B&) = delete;, compiler tells me I use a deleted function.
How is it possible that the copy constructor works with no implementation just with declaration?
Note: The example code is based on a much larger code that behaves the same way, hopefully I didn't leave something out.
The actual copy is elided by the compiler, which is allowed since the copy constructor is accessible. The compiler is of course under no obligation to elide this copy and if it didn't I would expect a linker error not finding the implementation of the copy constructor.

Any disadvantage of inheriting from boost::noncopyable vs delete copy ctor and op? [duplicate]

To prevent copying a class, you can very easily declare a private copy constructor / assignment operators. But you can also inherit boost::noncopyable.
What are the advantages / disadvantages of using boost in this case?
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.
Summarizing what others have said:
Advantages of boost::noncopyable over private copy methods:
It is more explicit and descriptive in the intent. Using private copy functions is an idiom that takes longer to spot than noncopyable.
It is less code / less typing / less clutter / less room for error (the easiest would be accidentally providing an implementation).
It embeds meaning right in the type's metadata, similar to a C# attribute. You can now write a function which accepts only objects which are noncopyable.
It potentially catches errors earlier in the build process. The error will be presented at compile-time rather than link-time, in the case that the class itself or friends of the class are doing the erroneous copying.
(almost the same as #4) Prevents the class itself or friends of the class from calling the private copy methods.
Advantages of private copy methods over boost::noncopyable:
No boost dependency
It makes the intent explicit and clear, otherwise one has to see the definition of the class,and search for the declaration related to copy-semantic, and then look for the access-specifier in which it is declared, in order to determine whether the class is noncopyable or not. Other way to discover it by writing code that requires copy-semantic enabled and see the compilation error.
The intent of boost::noncopyable is clearer.
Boost::noncopyable prevents the classes methods from accidentally using the private copy constructor.
Less code with boost::noncopyable.
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.
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
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.
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.
The advantage is that you don't have to write a private copy constructor and a private copy operator yourself and it expresses clearly your intention without writing additional documentation.
I'd rather use boost::noncopyable than manually delete or privatize the copy constructor and assignment operator.
However, I almost never use either method, because:
If I am making a non-copyable object, there has to be a reason it is non-copyable. This reason, 99% of the time, is because I have members that can't be copied meaningfully. Chances are, such members would also be better suited as private implementation details. So I make most such classes like this:
struct Whatever {
Whatever();
~Whatever();
private:
struct Detail;
std::unique_ptr<Detail> detail;
};
So now, I have a private implementation struct, and since I've used std::unique_ptr, my top-level class is non-copyable for free. The link errors that come from this are understandable because they talk about how you can't copy a std::unique_ptr. To me, this is all the benefits of boost::noncopyable and a private implementation rolled into one.
The benefit with this pattern is later, if I decide that I did indeed want to make my objects of this class copyable, I can just add and implement a copy constructor and/or assignment operator without changing the class hierarchy.
The disavantage, according to Scott Meyers, the name is "non-natrual", if you do need to find a disavantage of it.

What are the advantages of boost::noncopyable

To prevent copying a class, you can very easily declare a private copy constructor / assignment operators. But you can also inherit boost::noncopyable.
What are the advantages / disadvantages of using boost in this case?
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.
Summarizing what others have said:
Advantages of boost::noncopyable over private copy methods:
It is more explicit and descriptive in the intent. Using private copy functions is an idiom that takes longer to spot than noncopyable.
It is less code / less typing / less clutter / less room for error (the easiest would be accidentally providing an implementation).
It embeds meaning right in the type's metadata, similar to a C# attribute. You can now write a function which accepts only objects which are noncopyable.
It potentially catches errors earlier in the build process. The error will be presented at compile-time rather than link-time, in the case that the class itself or friends of the class are doing the erroneous copying.
(almost the same as #4) Prevents the class itself or friends of the class from calling the private copy methods.
Advantages of private copy methods over boost::noncopyable:
No boost dependency
It makes the intent explicit and clear, otherwise one has to see the definition of the class,and search for the declaration related to copy-semantic, and then look for the access-specifier in which it is declared, in order to determine whether the class is noncopyable or not. Other way to discover it by writing code that requires copy-semantic enabled and see the compilation error.
The intent of boost::noncopyable is clearer.
Boost::noncopyable prevents the classes methods from accidentally using the private copy constructor.
Less code with boost::noncopyable.
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.
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
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.
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.
The advantage is that you don't have to write a private copy constructor and a private copy operator yourself and it expresses clearly your intention without writing additional documentation.
I'd rather use boost::noncopyable than manually delete or privatize the copy constructor and assignment operator.
However, I almost never use either method, because:
If I am making a non-copyable object, there has to be a reason it is non-copyable. This reason, 99% of the time, is because I have members that can't be copied meaningfully. Chances are, such members would also be better suited as private implementation details. So I make most such classes like this:
struct Whatever {
Whatever();
~Whatever();
private:
struct Detail;
std::unique_ptr<Detail> detail;
};
So now, I have a private implementation struct, and since I've used std::unique_ptr, my top-level class is non-copyable for free. The link errors that come from this are understandable because they talk about how you can't copy a std::unique_ptr. To me, this is all the benefits of boost::noncopyable and a private implementation rolled into one.
The benefit with this pattern is later, if I decide that I did indeed want to make my objects of this class copyable, I can just add and implement a copy constructor and/or assignment operator without changing the class hierarchy.
The disavantage, according to Scott Meyers, the name is "non-natrual", if you do need to find a disavantage of it.