6

I am new to programming. sorry for my bad english. I have tried to use rvalue as initialiser to initial objects. So, according to the code, it would print out what are the used constructor and assignment operator. But turned out object "what2" and "what3", those don't print out anything. here is the code:

#include <iostream>
using namespace std;
class X{
public:
    int x;
    X()= default;
    X(int num):x{num}{}
    X(const X& y){
        x = y.x;
        std::cout << "copy constructor" << std::endl;
        std::cout << x << std::endl;

    }
    X& operator=(const X& d){
        x = d.x;
        std::cout << "copy assignment" << std::endl;
        return *this;
    }
    X(X&& y){
        x = y.x;
        std::cout << "move constructor" << std::endl;
    }
    X& operator=(X&& b){
        x = b.x;
        std::cout << "move assignment" << std::endl;
        return *this;
    }
};

X operator +(const X& a,const X& b){
    X tmp{};
    tmp.x = a.x +b.x;
    return tmp;
}

int main(int argc, const char * argv[]) {
    X a{7} , b{11};
    X what1;
    cout << "---------------" << endl;
    what1 = a+b;
    cout << "---------------" << endl;
    X what2{a+b};
    cout << "---------------" << endl;
    X what3 = a+b;
    cout << "---------------" << endl;
    std::cout << what1.x << std::endl;
    std::cout << what2.x << std:: endl;
    std::cout <<what3.x << std::endl;
    return 0;
}

the output is:

---------------
move assignment
---------------
---------------
---------------
18
18
18
Program ended with exit code: 0

only "what1" uses assignment properly. so, how can i use rvalue to initial an object? and using operator= to initial an object? thank you very much.

maazza
  • 7,016
  • 15
  • 63
  • 96
Carl Hung
  • 545
  • 4
  • 17

3 Answers3

5

Your code could result in move operations being used, but your compiler has chosen to elide those moves and allocate the return of operator+ directly at the call site. You can see this happening if you disable copy elision in your compiler (-fno-elide-constructors in GCC or Clang).

Your move constructor and assignment operator will be successfully used in contexts in which copy elision is not permitted, such as this:

X what2 { std::move(what1) }; //can't elide copy, move constructor used
Community
  • 1
  • 1
TartanLlama
  • 63,752
  • 13
  • 157
  • 193
  • X what3 = a+ b; // I want to know how it works. Just simply move? or create an empty object "what3", then move in? Thanks. – Carl Hung Jan 05 '16 at 16:08
  • 1
    With copy elision the return of `a+b` will be allocated directly into `what3`. Without, it's a single move-constructor call. This form is known as *copy-initialization*. – TartanLlama Jan 05 '16 at 16:57
0

GCC provides the -fno-elide-constructors option to disable copy-elision. if you want to elide the copy-elision then use flag -fno-elide-constructors. Refer https://stackoverflow.com/questions/12953127/what-are-copy-elision-and-return-value-optimization/27916892#27916892 for more detail

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
Ajay yadav
  • 4,141
  • 4
  • 31
  • 40
0

The following code triggers more of your constructors/operators, check it out to see which trigger in what cases

#include <iostream>
using namespace std;
class X{
public:
    int x;
    X()
    {
        x = 0;
        std::cout << "constructor" << std::endl;
    }
    X(int num):x{num}
    {
        std::cout << "list initilizer" << std::endl;
    }
    X(const X& y){
        x = y.x;
        std::cout << "copy constructor" << std::endl;
    }
    X& operator=(const X& d){
        x = d.x;
        std::cout << "copy assignment" << std::endl;
        return *this;
    }
    X(X&& y){
        x = y.x;
        std::cout << "move constructor" << std::endl;
    }
    X& operator=(X&& b){
        x = b.x;
        std::cout << "move assignment" << std::endl;
        return *this;
    }
};

X operator +(const X& a,const X& b){
    X tmp{};
    tmp.x = a.x +b.x;
    return tmp;
}

int main(int argc, const char * argv[]) {
    X a{7} , b{11};
    cout << "---------------" << endl;
    X what1;
    cout << "---------------" << endl;
    what1 = a+b;
    cout << "---------------" << endl;
    X what2(a+b);
    cout << "---------------" << endl;
    X what3 = X(a);
    cout << "---------------" << endl;
    X what4 = X();
    cout << "---------------" << endl;
    X what5 = std::move(what1);
    cout << "---------------" << endl;
    what5 = std::move(what1);
    cout << "---------------" << endl;
    what5 = what1;
    cout << "---------------" << endl;
    return 0;
}
nissefors
  • 430
  • 7
  • 13