Compiler not generating move constructors











up vote
7
down vote

favorite
1












I am trying to understand the move semantics are looking in to compiler generated move constructors (copy and assignment).
In Modern Effective C++, Scott Meyers says in Item #17 that if no explicit copy constructors are declared, the the compiler will generate move constructors, which will do member-wise move for non-static members.



To confirm this, I am trying below code:



#include <iostream>
#include <string>
using namespace std;

class A
{
private:
std::string str;

public:

A() : str("Init string")
{
cout << "Default constructor" << endl;
}

A(std::string _str) : str(_str)
{
cout << "Constructor with string" << endl;
}

std::string getString()
{
return str;
}
};

int main() {

A obj1;
A obj2("Obj2 string");

cout << endl;
cout << "obj1: " << obj1.getString() << endl;
cout << "obj2: " << obj2.getString() << endl;

obj1 = std::move(obj2);

cout << endl;
cout << "obj1: " << obj1.getString() << endl;
cout << "obj2: " << obj2.getString() << endl;

return 0;
}


The output is:



Default constructor
Constructor with string

obj1: Init string
obj2: Obj2 string

obj1: Obj2 string
obj2: Obj2 string


But I expected it to be:



Default constructor
Constructor with string

obj1: Init string
obj2: Obj2 string

obj1: Obj2 string
obj2:


Because obj2.str would have been moved and now has an empty string.



What is the reason the compiler is not generating a move assignment constructor and invoking the copy assignment operator?



EDIT:
Implementing the move assignment operator as below gives the expected output (i.e. empty string after calling std::move)



A& operator=(A&& obj)
{
cout << "Move assignment operator" << endl;
str = std::move(obj.str);
return *this;
}









share|improve this question
























  • Note that mid-2010s versions of MSVC didn't generate move constructors when they should have
    – M.M
    15 hours ago






  • 1




    Do another test with a long string (say 40 characters)
    – M.M
    15 hours ago















up vote
7
down vote

favorite
1












I am trying to understand the move semantics are looking in to compiler generated move constructors (copy and assignment).
In Modern Effective C++, Scott Meyers says in Item #17 that if no explicit copy constructors are declared, the the compiler will generate move constructors, which will do member-wise move for non-static members.



To confirm this, I am trying below code:



#include <iostream>
#include <string>
using namespace std;

class A
{
private:
std::string str;

public:

A() : str("Init string")
{
cout << "Default constructor" << endl;
}

A(std::string _str) : str(_str)
{
cout << "Constructor with string" << endl;
}

std::string getString()
{
return str;
}
};

int main() {

A obj1;
A obj2("Obj2 string");

cout << endl;
cout << "obj1: " << obj1.getString() << endl;
cout << "obj2: " << obj2.getString() << endl;

obj1 = std::move(obj2);

cout << endl;
cout << "obj1: " << obj1.getString() << endl;
cout << "obj2: " << obj2.getString() << endl;

return 0;
}


The output is:



Default constructor
Constructor with string

obj1: Init string
obj2: Obj2 string

obj1: Obj2 string
obj2: Obj2 string


But I expected it to be:



Default constructor
Constructor with string

obj1: Init string
obj2: Obj2 string

obj1: Obj2 string
obj2:


Because obj2.str would have been moved and now has an empty string.



What is the reason the compiler is not generating a move assignment constructor and invoking the copy assignment operator?



EDIT:
Implementing the move assignment operator as below gives the expected output (i.e. empty string after calling std::move)



A& operator=(A&& obj)
{
cout << "Move assignment operator" << endl;
str = std::move(obj.str);
return *this;
}









share|improve this question
























  • Note that mid-2010s versions of MSVC didn't generate move constructors when they should have
    – M.M
    15 hours ago






  • 1




    Do another test with a long string (say 40 characters)
    – M.M
    15 hours ago













up vote
7
down vote

favorite
1









up vote
7
down vote

favorite
1






1





I am trying to understand the move semantics are looking in to compiler generated move constructors (copy and assignment).
In Modern Effective C++, Scott Meyers says in Item #17 that if no explicit copy constructors are declared, the the compiler will generate move constructors, which will do member-wise move for non-static members.



To confirm this, I am trying below code:



#include <iostream>
#include <string>
using namespace std;

class A
{
private:
std::string str;

public:

A() : str("Init string")
{
cout << "Default constructor" << endl;
}

A(std::string _str) : str(_str)
{
cout << "Constructor with string" << endl;
}

std::string getString()
{
return str;
}
};

int main() {

A obj1;
A obj2("Obj2 string");

cout << endl;
cout << "obj1: " << obj1.getString() << endl;
cout << "obj2: " << obj2.getString() << endl;

obj1 = std::move(obj2);

cout << endl;
cout << "obj1: " << obj1.getString() << endl;
cout << "obj2: " << obj2.getString() << endl;

return 0;
}


The output is:



Default constructor
Constructor with string

obj1: Init string
obj2: Obj2 string

obj1: Obj2 string
obj2: Obj2 string


But I expected it to be:



Default constructor
Constructor with string

obj1: Init string
obj2: Obj2 string

obj1: Obj2 string
obj2:


Because obj2.str would have been moved and now has an empty string.



What is the reason the compiler is not generating a move assignment constructor and invoking the copy assignment operator?



EDIT:
Implementing the move assignment operator as below gives the expected output (i.e. empty string after calling std::move)



A& operator=(A&& obj)
{
cout << "Move assignment operator" << endl;
str = std::move(obj.str);
return *this;
}









share|improve this question















I am trying to understand the move semantics are looking in to compiler generated move constructors (copy and assignment).
In Modern Effective C++, Scott Meyers says in Item #17 that if no explicit copy constructors are declared, the the compiler will generate move constructors, which will do member-wise move for non-static members.



To confirm this, I am trying below code:



#include <iostream>
#include <string>
using namespace std;

class A
{
private:
std::string str;

public:

A() : str("Init string")
{
cout << "Default constructor" << endl;
}

A(std::string _str) : str(_str)
{
cout << "Constructor with string" << endl;
}

std::string getString()
{
return str;
}
};

int main() {

A obj1;
A obj2("Obj2 string");

cout << endl;
cout << "obj1: " << obj1.getString() << endl;
cout << "obj2: " << obj2.getString() << endl;

obj1 = std::move(obj2);

cout << endl;
cout << "obj1: " << obj1.getString() << endl;
cout << "obj2: " << obj2.getString() << endl;

return 0;
}


The output is:



Default constructor
Constructor with string

obj1: Init string
obj2: Obj2 string

obj1: Obj2 string
obj2: Obj2 string


But I expected it to be:



Default constructor
Constructor with string

obj1: Init string
obj2: Obj2 string

obj1: Obj2 string
obj2:


Because obj2.str would have been moved and now has an empty string.



What is the reason the compiler is not generating a move assignment constructor and invoking the copy assignment operator?



EDIT:
Implementing the move assignment operator as below gives the expected output (i.e. empty string after calling std::move)



A& operator=(A&& obj)
{
cout << "Move assignment operator" << endl;
str = std::move(obj.str);
return *this;
}






c++ c++11 move-semantics






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 12 hours ago

























asked 15 hours ago









madu

1,89783657




1,89783657












  • Note that mid-2010s versions of MSVC didn't generate move constructors when they should have
    – M.M
    15 hours ago






  • 1




    Do another test with a long string (say 40 characters)
    – M.M
    15 hours ago


















  • Note that mid-2010s versions of MSVC didn't generate move constructors when they should have
    – M.M
    15 hours ago






  • 1




    Do another test with a long string (say 40 characters)
    – M.M
    15 hours ago
















Note that mid-2010s versions of MSVC didn't generate move constructors when they should have
– M.M
15 hours ago




Note that mid-2010s versions of MSVC didn't generate move constructors when they should have
– M.M
15 hours ago




1




1




Do another test with a long string (say 40 characters)
– M.M
15 hours ago




Do another test with a long string (say 40 characters)
– M.M
15 hours ago












4 Answers
4






active

oldest

votes

















up vote
6
down vote













Firstly, obj1 = std::move(obj2); invokes assignment operator, so it has nothing to do with constructors.



Yes, The compiler generates a move assignment operator for A, which perform member-wise move operation, including data member str. The problem is that after move operation str is left in valid, but unspecified state. Also see std::basic_string::operator=.




Replaces the contents with those of str using move semantics. str is in a valid but unspecified state afterwards.




I think you might observe the same result with only std::string, e.g.



std::string str1 = "Init string";
std::string str2 = "Obj2 string";
str1 = std::move(str2);
std::cout << str2;




LIVE with clang, just for reference; it gives the result as you expected but still remember the result is unspecified.






share|improve this answer























  • Thank you. However, I see that when I implement the move assignment constructor, obj1 = std::move(obj) invokes that explicitly declared move assignment constructor, NOT the copy assignment operator.
    – madu
    14 hours ago












  • @madu How did you declare the move assignment constructor ? What's its signature?
    – songyuanyao
    14 hours ago










  • The signature is A& operator=(A&& obj). Wrong?
    – madu
    14 hours ago










  • @madu I see, yes this is assignment operator. :) Move constructor looks like A(A&& obj). They're different. So we don't say assignment constructor, which is confusing.
    – songyuanyao
    14 hours ago












  • Thanks. Yes, I see the difference. But the signature is correct for the move assignment operator, right?
    – madu
    14 hours ago


















up vote
3
down vote













The compiler is invoking the move-assignment operator, which causes obj1.str to be move-assigned from obj2.str. However, a move does not guarantee that the source object is empty; for most standard library classes, an object that has been moved from is left in a "valid but unspecified state". (The most obvious exception is that a std::unique_ptr<T> that has been moved from is guaranteed to be null.) It will often, but not always, be the case that a moved-from std::string is empty. In your case, the string "Obj2 string" is short enough that it might be stored inline (i.e., using the short string optimization). If that's the case, then the move-assignment operator must copy the string. Going back and emptying out the source string would then add extra overhead, so the implementation doesn't do it.






share|improve this answer





















  • Thank you Brian. But, when I explicitly implement move assignment operator and inside it do str = std::move(obj.str), I see that obj2.str is infact the empty string. Why do I see a different behavior in that case?
    – madu
    14 hours ago












  • @madu Can you provide steps required to reproduce both behaviours, i.e., with and without the user-provided move-assignment operator?
    – Brian
    12 hours ago










  • Thanks @Brian. I edited the original question and included the move assignment operator implementation that would give the output I am expecting.
    – madu
    12 hours ago


















up vote
2
down vote













The standard does not specify the state of a moved from object.




17.6.5.15 Moved-from state of library types
[lib.types.movedfrom]



Objects of types defined in the C++ standard library may be moved from (12.8). Move operations may be explicitly specified or implicitly generated. Unless otherwise specified, such moved-from objects shall be placed in a valid but unspecified state.




So your moved from string is in a valid but unspecified state. Do not except an empty string or the same value or a string containing "potato".



My guess here is that "Obj2 string" fits in the small string optimisation, which enable small strings to live on the stack instead of the heap. In this particular case, assigning by memcpy the string object to the other without any cleanup (eg, without setting the old string to empty) is actually faster.






share|improve this answer




























    up vote
    -2
    down vote













    Accessing the moved-from object is undefined behavior.

    All that is guaranteed is that it is deconstructable.



    You found the old string there, but you could have found as well a dump, pi, or the man in the moon there.






    share|improve this answer

















    • 7




      No it is not undefined behavior. You can get it's size, reassign it to a new value and do other stuff with a moved from object.
      – Guillaume Racicot
      15 hours ago










    • He accesses it with cout <<. Try not to nitpick, but to understand the obvious reference.
      – Aganju
      15 hours ago






    • 3




      @Aganju When a standard library class object is moved from, it is left in a "valid but unspecified state". This means that operations on that object that have no preconditions are still allowed. Printing the string in this manner is an example of such an allowed operation.
      – Brian
      12 hours ago











    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














     

    draft saved


    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53292389%2fcompiler-not-generating-move-constructors%23new-answer', 'question_page');
    }
    );

    Post as a guest
































    4 Answers
    4






    active

    oldest

    votes








    4 Answers
    4






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    6
    down vote













    Firstly, obj1 = std::move(obj2); invokes assignment operator, so it has nothing to do with constructors.



    Yes, The compiler generates a move assignment operator for A, which perform member-wise move operation, including data member str. The problem is that after move operation str is left in valid, but unspecified state. Also see std::basic_string::operator=.




    Replaces the contents with those of str using move semantics. str is in a valid but unspecified state afterwards.




    I think you might observe the same result with only std::string, e.g.



    std::string str1 = "Init string";
    std::string str2 = "Obj2 string";
    str1 = std::move(str2);
    std::cout << str2;




    LIVE with clang, just for reference; it gives the result as you expected but still remember the result is unspecified.






    share|improve this answer























    • Thank you. However, I see that when I implement the move assignment constructor, obj1 = std::move(obj) invokes that explicitly declared move assignment constructor, NOT the copy assignment operator.
      – madu
      14 hours ago












    • @madu How did you declare the move assignment constructor ? What's its signature?
      – songyuanyao
      14 hours ago










    • The signature is A& operator=(A&& obj). Wrong?
      – madu
      14 hours ago










    • @madu I see, yes this is assignment operator. :) Move constructor looks like A(A&& obj). They're different. So we don't say assignment constructor, which is confusing.
      – songyuanyao
      14 hours ago












    • Thanks. Yes, I see the difference. But the signature is correct for the move assignment operator, right?
      – madu
      14 hours ago















    up vote
    6
    down vote













    Firstly, obj1 = std::move(obj2); invokes assignment operator, so it has nothing to do with constructors.



    Yes, The compiler generates a move assignment operator for A, which perform member-wise move operation, including data member str. The problem is that after move operation str is left in valid, but unspecified state. Also see std::basic_string::operator=.




    Replaces the contents with those of str using move semantics. str is in a valid but unspecified state afterwards.




    I think you might observe the same result with only std::string, e.g.



    std::string str1 = "Init string";
    std::string str2 = "Obj2 string";
    str1 = std::move(str2);
    std::cout << str2;




    LIVE with clang, just for reference; it gives the result as you expected but still remember the result is unspecified.






    share|improve this answer























    • Thank you. However, I see that when I implement the move assignment constructor, obj1 = std::move(obj) invokes that explicitly declared move assignment constructor, NOT the copy assignment operator.
      – madu
      14 hours ago












    • @madu How did you declare the move assignment constructor ? What's its signature?
      – songyuanyao
      14 hours ago










    • The signature is A& operator=(A&& obj). Wrong?
      – madu
      14 hours ago










    • @madu I see, yes this is assignment operator. :) Move constructor looks like A(A&& obj). They're different. So we don't say assignment constructor, which is confusing.
      – songyuanyao
      14 hours ago












    • Thanks. Yes, I see the difference. But the signature is correct for the move assignment operator, right?
      – madu
      14 hours ago













    up vote
    6
    down vote










    up vote
    6
    down vote









    Firstly, obj1 = std::move(obj2); invokes assignment operator, so it has nothing to do with constructors.



    Yes, The compiler generates a move assignment operator for A, which perform member-wise move operation, including data member str. The problem is that after move operation str is left in valid, but unspecified state. Also see std::basic_string::operator=.




    Replaces the contents with those of str using move semantics. str is in a valid but unspecified state afterwards.




    I think you might observe the same result with only std::string, e.g.



    std::string str1 = "Init string";
    std::string str2 = "Obj2 string";
    str1 = std::move(str2);
    std::cout << str2;




    LIVE with clang, just for reference; it gives the result as you expected but still remember the result is unspecified.






    share|improve this answer














    Firstly, obj1 = std::move(obj2); invokes assignment operator, so it has nothing to do with constructors.



    Yes, The compiler generates a move assignment operator for A, which perform member-wise move operation, including data member str. The problem is that after move operation str is left in valid, but unspecified state. Also see std::basic_string::operator=.




    Replaces the contents with those of str using move semantics. str is in a valid but unspecified state afterwards.




    I think you might observe the same result with only std::string, e.g.



    std::string str1 = "Init string";
    std::string str2 = "Obj2 string";
    str1 = std::move(str2);
    std::cout << str2;




    LIVE with clang, just for reference; it gives the result as you expected but still remember the result is unspecified.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited 10 hours ago

























    answered 15 hours ago









    songyuanyao

    87.9k11169231




    87.9k11169231












    • Thank you. However, I see that when I implement the move assignment constructor, obj1 = std::move(obj) invokes that explicitly declared move assignment constructor, NOT the copy assignment operator.
      – madu
      14 hours ago












    • @madu How did you declare the move assignment constructor ? What's its signature?
      – songyuanyao
      14 hours ago










    • The signature is A& operator=(A&& obj). Wrong?
      – madu
      14 hours ago










    • @madu I see, yes this is assignment operator. :) Move constructor looks like A(A&& obj). They're different. So we don't say assignment constructor, which is confusing.
      – songyuanyao
      14 hours ago












    • Thanks. Yes, I see the difference. But the signature is correct for the move assignment operator, right?
      – madu
      14 hours ago


















    • Thank you. However, I see that when I implement the move assignment constructor, obj1 = std::move(obj) invokes that explicitly declared move assignment constructor, NOT the copy assignment operator.
      – madu
      14 hours ago












    • @madu How did you declare the move assignment constructor ? What's its signature?
      – songyuanyao
      14 hours ago










    • The signature is A& operator=(A&& obj). Wrong?
      – madu
      14 hours ago










    • @madu I see, yes this is assignment operator. :) Move constructor looks like A(A&& obj). They're different. So we don't say assignment constructor, which is confusing.
      – songyuanyao
      14 hours ago












    • Thanks. Yes, I see the difference. But the signature is correct for the move assignment operator, right?
      – madu
      14 hours ago
















    Thank you. However, I see that when I implement the move assignment constructor, obj1 = std::move(obj) invokes that explicitly declared move assignment constructor, NOT the copy assignment operator.
    – madu
    14 hours ago






    Thank you. However, I see that when I implement the move assignment constructor, obj1 = std::move(obj) invokes that explicitly declared move assignment constructor, NOT the copy assignment operator.
    – madu
    14 hours ago














    @madu How did you declare the move assignment constructor ? What's its signature?
    – songyuanyao
    14 hours ago




    @madu How did you declare the move assignment constructor ? What's its signature?
    – songyuanyao
    14 hours ago












    The signature is A& operator=(A&& obj). Wrong?
    – madu
    14 hours ago




    The signature is A& operator=(A&& obj). Wrong?
    – madu
    14 hours ago












    @madu I see, yes this is assignment operator. :) Move constructor looks like A(A&& obj). They're different. So we don't say assignment constructor, which is confusing.
    – songyuanyao
    14 hours ago






    @madu I see, yes this is assignment operator. :) Move constructor looks like A(A&& obj). They're different. So we don't say assignment constructor, which is confusing.
    – songyuanyao
    14 hours ago














    Thanks. Yes, I see the difference. But the signature is correct for the move assignment operator, right?
    – madu
    14 hours ago




    Thanks. Yes, I see the difference. But the signature is correct for the move assignment operator, right?
    – madu
    14 hours ago












    up vote
    3
    down vote













    The compiler is invoking the move-assignment operator, which causes obj1.str to be move-assigned from obj2.str. However, a move does not guarantee that the source object is empty; for most standard library classes, an object that has been moved from is left in a "valid but unspecified state". (The most obvious exception is that a std::unique_ptr<T> that has been moved from is guaranteed to be null.) It will often, but not always, be the case that a moved-from std::string is empty. In your case, the string "Obj2 string" is short enough that it might be stored inline (i.e., using the short string optimization). If that's the case, then the move-assignment operator must copy the string. Going back and emptying out the source string would then add extra overhead, so the implementation doesn't do it.






    share|improve this answer





















    • Thank you Brian. But, when I explicitly implement move assignment operator and inside it do str = std::move(obj.str), I see that obj2.str is infact the empty string. Why do I see a different behavior in that case?
      – madu
      14 hours ago












    • @madu Can you provide steps required to reproduce both behaviours, i.e., with and without the user-provided move-assignment operator?
      – Brian
      12 hours ago










    • Thanks @Brian. I edited the original question and included the move assignment operator implementation that would give the output I am expecting.
      – madu
      12 hours ago















    up vote
    3
    down vote













    The compiler is invoking the move-assignment operator, which causes obj1.str to be move-assigned from obj2.str. However, a move does not guarantee that the source object is empty; for most standard library classes, an object that has been moved from is left in a "valid but unspecified state". (The most obvious exception is that a std::unique_ptr<T> that has been moved from is guaranteed to be null.) It will often, but not always, be the case that a moved-from std::string is empty. In your case, the string "Obj2 string" is short enough that it might be stored inline (i.e., using the short string optimization). If that's the case, then the move-assignment operator must copy the string. Going back and emptying out the source string would then add extra overhead, so the implementation doesn't do it.






    share|improve this answer





















    • Thank you Brian. But, when I explicitly implement move assignment operator and inside it do str = std::move(obj.str), I see that obj2.str is infact the empty string. Why do I see a different behavior in that case?
      – madu
      14 hours ago












    • @madu Can you provide steps required to reproduce both behaviours, i.e., with and without the user-provided move-assignment operator?
      – Brian
      12 hours ago










    • Thanks @Brian. I edited the original question and included the move assignment operator implementation that would give the output I am expecting.
      – madu
      12 hours ago













    up vote
    3
    down vote










    up vote
    3
    down vote









    The compiler is invoking the move-assignment operator, which causes obj1.str to be move-assigned from obj2.str. However, a move does not guarantee that the source object is empty; for most standard library classes, an object that has been moved from is left in a "valid but unspecified state". (The most obvious exception is that a std::unique_ptr<T> that has been moved from is guaranteed to be null.) It will often, but not always, be the case that a moved-from std::string is empty. In your case, the string "Obj2 string" is short enough that it might be stored inline (i.e., using the short string optimization). If that's the case, then the move-assignment operator must copy the string. Going back and emptying out the source string would then add extra overhead, so the implementation doesn't do it.






    share|improve this answer












    The compiler is invoking the move-assignment operator, which causes obj1.str to be move-assigned from obj2.str. However, a move does not guarantee that the source object is empty; for most standard library classes, an object that has been moved from is left in a "valid but unspecified state". (The most obvious exception is that a std::unique_ptr<T> that has been moved from is guaranteed to be null.) It will often, but not always, be the case that a moved-from std::string is empty. In your case, the string "Obj2 string" is short enough that it might be stored inline (i.e., using the short string optimization). If that's the case, then the move-assignment operator must copy the string. Going back and emptying out the source string would then add extra overhead, so the implementation doesn't do it.







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered 15 hours ago









    Brian

    62.6k792176




    62.6k792176












    • Thank you Brian. But, when I explicitly implement move assignment operator and inside it do str = std::move(obj.str), I see that obj2.str is infact the empty string. Why do I see a different behavior in that case?
      – madu
      14 hours ago












    • @madu Can you provide steps required to reproduce both behaviours, i.e., with and without the user-provided move-assignment operator?
      – Brian
      12 hours ago










    • Thanks @Brian. I edited the original question and included the move assignment operator implementation that would give the output I am expecting.
      – madu
      12 hours ago


















    • Thank you Brian. But, when I explicitly implement move assignment operator and inside it do str = std::move(obj.str), I see that obj2.str is infact the empty string. Why do I see a different behavior in that case?
      – madu
      14 hours ago












    • @madu Can you provide steps required to reproduce both behaviours, i.e., with and without the user-provided move-assignment operator?
      – Brian
      12 hours ago










    • Thanks @Brian. I edited the original question and included the move assignment operator implementation that would give the output I am expecting.
      – madu
      12 hours ago
















    Thank you Brian. But, when I explicitly implement move assignment operator and inside it do str = std::move(obj.str), I see that obj2.str is infact the empty string. Why do I see a different behavior in that case?
    – madu
    14 hours ago






    Thank you Brian. But, when I explicitly implement move assignment operator and inside it do str = std::move(obj.str), I see that obj2.str is infact the empty string. Why do I see a different behavior in that case?
    – madu
    14 hours ago














    @madu Can you provide steps required to reproduce both behaviours, i.e., with and without the user-provided move-assignment operator?
    – Brian
    12 hours ago




    @madu Can you provide steps required to reproduce both behaviours, i.e., with and without the user-provided move-assignment operator?
    – Brian
    12 hours ago












    Thanks @Brian. I edited the original question and included the move assignment operator implementation that would give the output I am expecting.
    – madu
    12 hours ago




    Thanks @Brian. I edited the original question and included the move assignment operator implementation that would give the output I am expecting.
    – madu
    12 hours ago










    up vote
    2
    down vote













    The standard does not specify the state of a moved from object.




    17.6.5.15 Moved-from state of library types
    [lib.types.movedfrom]



    Objects of types defined in the C++ standard library may be moved from (12.8). Move operations may be explicitly specified or implicitly generated. Unless otherwise specified, such moved-from objects shall be placed in a valid but unspecified state.




    So your moved from string is in a valid but unspecified state. Do not except an empty string or the same value or a string containing "potato".



    My guess here is that "Obj2 string" fits in the small string optimisation, which enable small strings to live on the stack instead of the heap. In this particular case, assigning by memcpy the string object to the other without any cleanup (eg, without setting the old string to empty) is actually faster.






    share|improve this answer

























      up vote
      2
      down vote













      The standard does not specify the state of a moved from object.




      17.6.5.15 Moved-from state of library types
      [lib.types.movedfrom]



      Objects of types defined in the C++ standard library may be moved from (12.8). Move operations may be explicitly specified or implicitly generated. Unless otherwise specified, such moved-from objects shall be placed in a valid but unspecified state.




      So your moved from string is in a valid but unspecified state. Do not except an empty string or the same value or a string containing "potato".



      My guess here is that "Obj2 string" fits in the small string optimisation, which enable small strings to live on the stack instead of the heap. In this particular case, assigning by memcpy the string object to the other without any cleanup (eg, without setting the old string to empty) is actually faster.






      share|improve this answer























        up vote
        2
        down vote










        up vote
        2
        down vote









        The standard does not specify the state of a moved from object.




        17.6.5.15 Moved-from state of library types
        [lib.types.movedfrom]



        Objects of types defined in the C++ standard library may be moved from (12.8). Move operations may be explicitly specified or implicitly generated. Unless otherwise specified, such moved-from objects shall be placed in a valid but unspecified state.




        So your moved from string is in a valid but unspecified state. Do not except an empty string or the same value or a string containing "potato".



        My guess here is that "Obj2 string" fits in the small string optimisation, which enable small strings to live on the stack instead of the heap. In this particular case, assigning by memcpy the string object to the other without any cleanup (eg, without setting the old string to empty) is actually faster.






        share|improve this answer












        The standard does not specify the state of a moved from object.




        17.6.5.15 Moved-from state of library types
        [lib.types.movedfrom]



        Objects of types defined in the C++ standard library may be moved from (12.8). Move operations may be explicitly specified or implicitly generated. Unless otherwise specified, such moved-from objects shall be placed in a valid but unspecified state.




        So your moved from string is in a valid but unspecified state. Do not except an empty string or the same value or a string containing "potato".



        My guess here is that "Obj2 string" fits in the small string optimisation, which enable small strings to live on the stack instead of the heap. In this particular case, assigning by memcpy the string object to the other without any cleanup (eg, without setting the old string to empty) is actually faster.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered 15 hours ago









        Guillaume Racicot

        13k43163




        13k43163






















            up vote
            -2
            down vote













            Accessing the moved-from object is undefined behavior.

            All that is guaranteed is that it is deconstructable.



            You found the old string there, but you could have found as well a dump, pi, or the man in the moon there.






            share|improve this answer

















            • 7




              No it is not undefined behavior. You can get it's size, reassign it to a new value and do other stuff with a moved from object.
              – Guillaume Racicot
              15 hours ago










            • He accesses it with cout <<. Try not to nitpick, but to understand the obvious reference.
              – Aganju
              15 hours ago






            • 3




              @Aganju When a standard library class object is moved from, it is left in a "valid but unspecified state". This means that operations on that object that have no preconditions are still allowed. Printing the string in this manner is an example of such an allowed operation.
              – Brian
              12 hours ago















            up vote
            -2
            down vote













            Accessing the moved-from object is undefined behavior.

            All that is guaranteed is that it is deconstructable.



            You found the old string there, but you could have found as well a dump, pi, or the man in the moon there.






            share|improve this answer

















            • 7




              No it is not undefined behavior. You can get it's size, reassign it to a new value and do other stuff with a moved from object.
              – Guillaume Racicot
              15 hours ago










            • He accesses it with cout <<. Try not to nitpick, but to understand the obvious reference.
              – Aganju
              15 hours ago






            • 3




              @Aganju When a standard library class object is moved from, it is left in a "valid but unspecified state". This means that operations on that object that have no preconditions are still allowed. Printing the string in this manner is an example of such an allowed operation.
              – Brian
              12 hours ago













            up vote
            -2
            down vote










            up vote
            -2
            down vote









            Accessing the moved-from object is undefined behavior.

            All that is guaranteed is that it is deconstructable.



            You found the old string there, but you could have found as well a dump, pi, or the man in the moon there.






            share|improve this answer












            Accessing the moved-from object is undefined behavior.

            All that is guaranteed is that it is deconstructable.



            You found the old string there, but you could have found as well a dump, pi, or the man in the moon there.







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered 15 hours ago









            Aganju

            4,9851621




            4,9851621








            • 7




              No it is not undefined behavior. You can get it's size, reassign it to a new value and do other stuff with a moved from object.
              – Guillaume Racicot
              15 hours ago










            • He accesses it with cout <<. Try not to nitpick, but to understand the obvious reference.
              – Aganju
              15 hours ago






            • 3




              @Aganju When a standard library class object is moved from, it is left in a "valid but unspecified state". This means that operations on that object that have no preconditions are still allowed. Printing the string in this manner is an example of such an allowed operation.
              – Brian
              12 hours ago














            • 7




              No it is not undefined behavior. You can get it's size, reassign it to a new value and do other stuff with a moved from object.
              – Guillaume Racicot
              15 hours ago










            • He accesses it with cout <<. Try not to nitpick, but to understand the obvious reference.
              – Aganju
              15 hours ago






            • 3




              @Aganju When a standard library class object is moved from, it is left in a "valid but unspecified state". This means that operations on that object that have no preconditions are still allowed. Printing the string in this manner is an example of such an allowed operation.
              – Brian
              12 hours ago








            7




            7




            No it is not undefined behavior. You can get it's size, reassign it to a new value and do other stuff with a moved from object.
            – Guillaume Racicot
            15 hours ago




            No it is not undefined behavior. You can get it's size, reassign it to a new value and do other stuff with a moved from object.
            – Guillaume Racicot
            15 hours ago












            He accesses it with cout <<. Try not to nitpick, but to understand the obvious reference.
            – Aganju
            15 hours ago




            He accesses it with cout <<. Try not to nitpick, but to understand the obvious reference.
            – Aganju
            15 hours ago




            3




            3




            @Aganju When a standard library class object is moved from, it is left in a "valid but unspecified state". This means that operations on that object that have no preconditions are still allowed. Printing the string in this manner is an example of such an allowed operation.
            – Brian
            12 hours ago




            @Aganju When a standard library class object is moved from, it is left in a "valid but unspecified state". This means that operations on that object that have no preconditions are still allowed. Printing the string in this manner is an example of such an allowed operation.
            – Brian
            12 hours ago


















             

            draft saved


            draft discarded



















































             


            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53292389%2fcompiler-not-generating-move-constructors%23new-answer', 'question_page');
            }
            );

            Post as a guest




















































































            Popular posts from this blog

            Plaza Victoria

            Puebla de Zaragoza

            Musa