How to enforce a calling of a moving constructor (C++)? - c++

I have this couple of code-lines:
#include <iostream>
using namespace std;
class A
{
public:
A() noexcept
{
cout << "A::A()" << endl;
}
A(const A&) noexcept
{
cout << "A::A(const A&)" << endl;
}
A(A&&) noexcept
{
cout << "A::A(A&&)" << endl;
}
};
class B
{
public:
B(const A& a) noexcept :
_a(a)
{}
B(A&& a) noexcept :
_a(a)
{}
private:
A _a;
};
int main(int argc, char* argv[])
{
A a;
B b1 = B(a);
B b2 = B(A());
}
They produce this output:
A::A()
A::A(const A&)
A::A()
A::A(const A&)
What need I to do in order to the A::A(A&&) will be called from the B::B(A&&)?
As you can see adding noexcept does not solve this issue.

Although the type of a is an rvalue reference to A, a itself is an lvalue. To retain its rvalue-ness, you need to use std::move:
B(A&& a) noexcept :
_a(std::move(a))
{}

Related

How to swap two objects without copy assignment operator?

I have a class A where, the copy assignment operator is deleted. How should I swap two instances of A ?
I tried using std::swap but that did not work.
class A {
private:
int a;
public:
A& operator=(const A& other) = delete;
A(int _a = 0):a(_a){}
void showA() { std::cout << a << std::endl; }
};
int main()
{
A obj1(10);
A obj2(20);
obj1.showA();
obj2.showA();
//A temp;
//temp = obj1;
//obj1 = obj2;
//obj2 = temp;
obj1.showA();
obj2.showA();
}
I expect obj1 and obj2 to be swapped. Initially obj1.a is 10 and obj2.a is 20, I expect obj1.a to be 20 and obj2.ato be 10 when done.
As #Yksisarvinen indicated you need to have move constructor and move assignment defined in order to get std::move to work:
#include <iostream>
#include <utility>
class A {
private:
int a;
public:
A(int a_) : a(a_) {}
A(const A& other) = delete;
A& operator=(const A&) = delete;
A(A&& other) {
a = other.a;
}
A& operator=(A&& other) {
a = other.a;
return *this;
}
void showA() { std::cout << a << std::endl; }
};
int main(int argc, char* argv[]) {
A obj1(10);
A obj2(20);
obj1.showA();
obj2.showA();
std::swap(obj1, obj2);
std::cout << "swapped:" << std::endl;
obj1.showA();
obj2.showA();
return 0;
}

Creating string class with static information [duplicate]

I want to inherit copy constructor of the base class using using keyword:
#include <iostream>
struct A
{
A() = default;
A(const A &) { std::cerr << __PRETTY_FUNCTION__ << std::endl; }
A( A &&) { std::cerr << __PRETTY_FUNCTION__ << std::endl; }
A& operator=(const A &) { std::cerr << __PRETTY_FUNCTION__ << std::endl; return *this; }
A& operator=( A &&) { std::cerr << __PRETTY_FUNCTION__ << std::endl; return *this; }
};
struct B : A
{
using A::A;
using A::operator=;
B& operator=(const B &) { std::cerr << __PRETTY_FUNCTION__ << std::endl; return *this; }
B& operator=( B &&) { std::cerr << __PRETTY_FUNCTION__ << std::endl; return *this; }
};
int main()
{
A a;
B b;
b = a; // OK
B b1( a ); // compile error
B b2(std::move(a)); // compile error
return 0;
}
Inheriting assignment operator using using keyword works OK, but inheriting copy and move constructors causes a compilation error: an inherited constructor is not a candidate for initialization from an expression of the same or derived type.
http://coliru.stacked-crooked.com/a/fe84b429c391c894:
main.cpp:16:14: note: an inherited constructor is not a candidate for initialization from an expression of the same or derived type
main.cpp:8:5: note: candidate: A::A(A&&)
A( A &&) { std::cerr << __PRETTY_FUNCTION__ << std::endl; }
^
main.cpp:16:14: note: inherited here
using A::A;
Why can I inherit assignment operator but cannot inherit copy constructor? What is a difference? I could understand if I couldn't inherit assignment operators too. But inheriting assignment operators in contrary is considered OK. That is a little strange for me.
The story
What I want is similar to what is asked in this question: I want to just add new methods to existing class without modifying it (it's a class from another library).
http://coliru.stacked-crooked.com/a/149a6194717cd465:
#include <iostream>
struct A // not my class
{
};
struct B : A
{
using A::A;
using A::operator=;
void foo() { std::cerr << "fuu" << std::endl; }
};
A NotMyFunc()
{
return {};
}
int main()
{
B b(NotMyFunc());
b.foo();
return 0;
}
But I don't want to reimplement copy and move constructors.
You need a constructor for B that has A as parameter. Then you need to make the default constructor explicit.
struct B : A
{
using A::A;
using A::operator=;
B() = default;
B(const A& a) : A(a) {}
B(A &&a): A(std::move(a)) {}
};

How does the default operator= works in C++?

I've had some hard times trying to understand how the default copy constructor and the default operator= work in C++.
In the following program, I don't see why the last line c0 = b2; cout <<endl; prints out 32944 .
-Does the operator= call the copy constructor if defined ? if not how does it behave ? in this case it seems that b0 when assingned to c0 used the copy constructor:
C(const B& x) : B(x), a(1){z=0; cout <<"9";}
-How did the statement c0 = b2; use the operator= of the class A (the 44 at the end of the result)?
#include <iostream>
using namespace std;
class A{
public:
A(){x=0; cout << "1";}
A(int t) {x=t; cout << "2";}
A(const A& a) {x=a.x; cout << "3";}
const A& operator=(const A& a) {x=a.x; cout << "4"; return *this;}
protected:
int x;
};
class B{
public:
B(const A& a=A()) : y(a) { cout << "5";}
B(const A& b, int u){y=b; k=u; cout << "6";}
protected:
A y; int k;
};
class C : public B{
public:
C(int t=1) {z=t; cout <<"7"; }
C(A x) : B(x) {z=0; cout <<"8";}
C(const B& x) : B(x), a(1){z=0; cout <<"9";}
protected:
A a; int z;
};
int main(){
B b2; cout << endl;
C c0; cout <<endl;
c0 = b2; cout <<endl;
return 0;
}
c0 = b2 prints out 32944 correctly.
c0 = b2 calls c0 = C(b2), y.operator= (4) and a.operator= (4)
C(b2) calls B(b2), A(1) (2) and cout << 9 (9)
B(b2) calls A(b2)
A(b2) calls cout << 3 (3)
From down to up: 3 2 9 4 and your final 4.

Automatic generation of the move constructor

#include <iostream>
using namespace std;
struct A
{
A() {}
A(const A &a) {
cout << "copy constructor" << endl;
}
A& operator=(const A &a) {
cout << "assigment operator" << endl;
}
A(A &&a) {
cout << "move" << endl;
}
A& operator=(A &&a) {
cout << "move" << endl;
}
};
struct B {
A a;
};
B func() {
B b;
return b;
}
int main() {
B b = func();
}
This prints "copy constructor".
For class B the move constructor and the move assignment operator should be automatic generated correct? But why is it using the copy constructor of class A and not the move constructor?
For me it doesn't print anything at all because the copy/move has been elided. However if I thwart RVO with something like:
extern bool choice;
B func() {
B b1, b2;
if (choice)
return b1;
return b2;
}
Then it prints:
move
It may be that your compiler does not yet implement the automatic generation of the move members.

Passing a const reference down a chain of constructors

I get a runtime error with the following code, which is a reproducible reduction of my actual code. I am sure I am not instantiating something properly, but I cannot figure out what it is.
#include <iostream>
using namespace std;
class A {
int n;
public:
A();
A(const int k);
int getn() const { return n; };
};
A::A() : n(0) {};
A::A(const int k) : n(k) {}
class B {
const A& myA;
public:
B(const A& anA);
int getn() const { return myA.getn(); };
};
B::B(const A& anA) : myA(anA) {}
class C {
const A& myA;
const B& myB;
public:
C(const A& anA);
int getn() const { return myB.getn(); };
};
C::C(const A& anA) : myA(anA), myB(myA) {}
class D {
A myA;
C myC;
public:
D(const int k);
int getAn() const { return myA.getn(); };
int getCn() const { return myC.getn(); };
};
D::D(const int k) : myA(k), myC(myA) {}
int main() {
D myD(10);
cerr << "A: " << myD.getAn() << '\n';
cerr << "C: " << myD.getCn() << '\n';
}
I either get a segmentation fault on the second line of output or "C:0", instead of "C:10" which I expect.
The problem is in this line:
C::C(const A& anA) : myA(anA), myB(myA) {}
myB is a reference. But to what? The answer is to a temporary. myB(myA) will construct a temp object that is assigned to your reference. Unfortunately this object will be destroyed after the Ctor exits.
Change your code to the following:
class C {
const A& myA;
const B myB;
public:...
and it should work.
BTW: I nearly always declare constructors with one argument as explicit. Do so and the compiler will warn you.
You are trying to initialize D::myC with reference to D::myA, this is not correct because object is not completely constructed at this moment.
D::D(const int k) : myA(k), myC(myA) {}