Compiler not generating move constructors
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
add a comment |
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
Note that mid-2010s versions of MSVC didn't generate move constructors when they should have
– M.M
Nov 14 '18 at 2:49
2
Do another test with a long string (say 40 characters)
– M.M
Nov 14 '18 at 2:50
add a comment |
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
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
c++ c++11 move-semantics
edited Nov 14 '18 at 6:05
madu
asked Nov 14 '18 at 2:35
madumadu
1,97983658
1,97983658
Note that mid-2010s versions of MSVC didn't generate move constructors when they should have
– M.M
Nov 14 '18 at 2:49
2
Do another test with a long string (say 40 characters)
– M.M
Nov 14 '18 at 2:50
add a comment |
Note that mid-2010s versions of MSVC didn't generate move constructors when they should have
– M.M
Nov 14 '18 at 2:49
2
Do another test with a long string (say 40 characters)
– M.M
Nov 14 '18 at 2:50
Note that mid-2010s versions of MSVC didn't generate move constructors when they should have
– M.M
Nov 14 '18 at 2:49
Note that mid-2010s versions of MSVC didn't generate move constructors when they should have
– M.M
Nov 14 '18 at 2:49
2
2
Do another test with a long string (say 40 characters)
– M.M
Nov 14 '18 at 2:50
Do another test with a long string (say 40 characters)
– M.M
Nov 14 '18 at 2:50
add a comment |
3 Answers
3
active
oldest
votes
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.
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
Nov 14 '18 at 4:10
@madu How did you declare the move assignment constructor ? What's its signature?
– songyuanyao
Nov 14 '18 at 4:12
The signature is A& operator=(A&& obj). Wrong?
– madu
Nov 14 '18 at 4:13
@madu I see, yes this is assignment operator. :) Move constructor looks likeA(A&& obj)
. They're different. So we don't say assignment constructor, which is confusing.
– songyuanyao
Nov 14 '18 at 4:15
Thanks. Yes, I see the difference. But the signature is correct for the move assignment operator, right?
– madu
Nov 14 '18 at 4:20
|
show 1 more comment
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.
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
Nov 14 '18 at 4:11
@madu Can you provide steps required to reproduce both behaviours, i.e., with and without the user-provided move-assignment operator?
– Brian
Nov 14 '18 at 5:37
Thanks @Brian. I edited the original question and included the move assignment operator implementation that would give the output I am expecting.
– madu
Nov 14 '18 at 6:06
add a comment |
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.
add a comment |
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',
autoActivateHeartbeat: false,
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
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
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.
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
Nov 14 '18 at 4:10
@madu How did you declare the move assignment constructor ? What's its signature?
– songyuanyao
Nov 14 '18 at 4:12
The signature is A& operator=(A&& obj). Wrong?
– madu
Nov 14 '18 at 4:13
@madu I see, yes this is assignment operator. :) Move constructor looks likeA(A&& obj)
. They're different. So we don't say assignment constructor, which is confusing.
– songyuanyao
Nov 14 '18 at 4:15
Thanks. Yes, I see the difference. But the signature is correct for the move assignment operator, right?
– madu
Nov 14 '18 at 4:20
|
show 1 more comment
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.
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
Nov 14 '18 at 4:10
@madu How did you declare the move assignment constructor ? What's its signature?
– songyuanyao
Nov 14 '18 at 4:12
The signature is A& operator=(A&& obj). Wrong?
– madu
Nov 14 '18 at 4:13
@madu I see, yes this is assignment operator. :) Move constructor looks likeA(A&& obj)
. They're different. So we don't say assignment constructor, which is confusing.
– songyuanyao
Nov 14 '18 at 4:15
Thanks. Yes, I see the difference. But the signature is correct for the move assignment operator, right?
– madu
Nov 14 '18 at 4:20
|
show 1 more comment
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.
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.
edited Nov 14 '18 at 7:48
answered Nov 14 '18 at 2:47
songyuanyaosongyuanyao
91.1k11173235
91.1k11173235
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
Nov 14 '18 at 4:10
@madu How did you declare the move assignment constructor ? What's its signature?
– songyuanyao
Nov 14 '18 at 4:12
The signature is A& operator=(A&& obj). Wrong?
– madu
Nov 14 '18 at 4:13
@madu I see, yes this is assignment operator. :) Move constructor looks likeA(A&& obj)
. They're different. So we don't say assignment constructor, which is confusing.
– songyuanyao
Nov 14 '18 at 4:15
Thanks. Yes, I see the difference. But the signature is correct for the move assignment operator, right?
– madu
Nov 14 '18 at 4:20
|
show 1 more comment
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
Nov 14 '18 at 4:10
@madu How did you declare the move assignment constructor ? What's its signature?
– songyuanyao
Nov 14 '18 at 4:12
The signature is A& operator=(A&& obj). Wrong?
– madu
Nov 14 '18 at 4:13
@madu I see, yes this is assignment operator. :) Move constructor looks likeA(A&& obj)
. They're different. So we don't say assignment constructor, which is confusing.
– songyuanyao
Nov 14 '18 at 4:15
Thanks. Yes, I see the difference. But the signature is correct for the move assignment operator, right?
– madu
Nov 14 '18 at 4:20
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
Nov 14 '18 at 4:10
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
Nov 14 '18 at 4:10
@madu How did you declare the move assignment constructor ? What's its signature?
– songyuanyao
Nov 14 '18 at 4:12
@madu How did you declare the move assignment constructor ? What's its signature?
– songyuanyao
Nov 14 '18 at 4:12
The signature is A& operator=(A&& obj). Wrong?
– madu
Nov 14 '18 at 4:13
The signature is A& operator=(A&& obj). Wrong?
– madu
Nov 14 '18 at 4:13
@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
Nov 14 '18 at 4:15
@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
Nov 14 '18 at 4:15
Thanks. Yes, I see the difference. But the signature is correct for the move assignment operator, right?
– madu
Nov 14 '18 at 4:20
Thanks. Yes, I see the difference. But the signature is correct for the move assignment operator, right?
– madu
Nov 14 '18 at 4:20
|
show 1 more comment
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.
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
Nov 14 '18 at 4:11
@madu Can you provide steps required to reproduce both behaviours, i.e., with and without the user-provided move-assignment operator?
– Brian
Nov 14 '18 at 5:37
Thanks @Brian. I edited the original question and included the move assignment operator implementation that would give the output I am expecting.
– madu
Nov 14 '18 at 6:06
add a comment |
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.
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
Nov 14 '18 at 4:11
@madu Can you provide steps required to reproduce both behaviours, i.e., with and without the user-provided move-assignment operator?
– Brian
Nov 14 '18 at 5:37
Thanks @Brian. I edited the original question and included the move assignment operator implementation that would give the output I am expecting.
– madu
Nov 14 '18 at 6:06
add a comment |
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.
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.
answered Nov 14 '18 at 2:44
BrianBrian
64.5k796183
64.5k796183
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
Nov 14 '18 at 4:11
@madu Can you provide steps required to reproduce both behaviours, i.e., with and without the user-provided move-assignment operator?
– Brian
Nov 14 '18 at 5:37
Thanks @Brian. I edited the original question and included the move assignment operator implementation that would give the output I am expecting.
– madu
Nov 14 '18 at 6:06
add a comment |
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
Nov 14 '18 at 4:11
@madu Can you provide steps required to reproduce both behaviours, i.e., with and without the user-provided move-assignment operator?
– Brian
Nov 14 '18 at 5:37
Thanks @Brian. I edited the original question and included the move assignment operator implementation that would give the output I am expecting.
– madu
Nov 14 '18 at 6:06
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
Nov 14 '18 at 4:11
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
Nov 14 '18 at 4:11
@madu Can you provide steps required to reproduce both behaviours, i.e., with and without the user-provided move-assignment operator?
– Brian
Nov 14 '18 at 5:37
@madu Can you provide steps required to reproduce both behaviours, i.e., with and without the user-provided move-assignment operator?
– Brian
Nov 14 '18 at 5:37
Thanks @Brian. I edited the original question and included the move assignment operator implementation that would give the output I am expecting.
– madu
Nov 14 '18 at 6:06
Thanks @Brian. I edited the original question and included the move assignment operator implementation that would give the output I am expecting.
– madu
Nov 14 '18 at 6:06
add a comment |
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.
add a comment |
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.
add a comment |
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.
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.
answered Nov 14 '18 at 2:44
Guillaume RacicotGuillaume Racicot
13.7k43264
13.7k43264
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Note that mid-2010s versions of MSVC didn't generate move constructors when they should have
– M.M
Nov 14 '18 at 2:49
2
Do another test with a long string (say 40 characters)
– M.M
Nov 14 '18 at 2:50