Trying to use c++ move constructor...and fail - c++

Right when I thought I understood what std::move and move constructors do, I tried to write some unit test, actually testing the move constructor for some class...
To my surprise I found, that I cannot think of a way to construct code which actually calls the move constructor. Worse, I cannot even set a breakpoint in the body of the move constructor (in VS2013 community edition, debug, 64bit build).
Wondering if this is a compiler peculiarity, I knocked up some small test code on my freebsd virtual machine, using clang (3.4.1). There, too I fail to find a way to get that move constructor invoked.
#include <iostream>
#include <stdint.h>
#include <string>
#include <algorithm>
#include <functional>
#include <ctype.h>
#include <locale>
void InPlaceToUpper( std::string& target )
{
std::transform(target.begin(), target.end(), target.begin(), ::toupper);
}
void InPlaceToLower( std::string& target )
{
std::transform(target.begin(), target.end(), target.begin(), ::tolower);
}
std::string ToUpper( const std::string& s )
{
std::string result;
result.resize(s.length());
std::transform(s.begin(), s.end(), result.begin(), ::toupper);
return result;
}
std::string ToLower( const std::string& s)
{
std::string result;
result.resize(s.length());
std::transform(s.begin(), s.end(), result.begin(), ::tolower);
return result;
}
class CFoo
{
std::string m_value;
public:
CFoo()
: m_value()
{
std::cout << "CFoo() called." << std::endl;
}
CFoo(const char *value)
: m_value(value)
{
std::cout << "CFoo(const char *) called." << std::endl;
}
CFoo(const std::string& value )
: m_value(value)
{
std::cout << "CFoo(const std::string&) called." << std::endl;
}
CFoo(const CFoo& other )
: m_value(other.m_value)
{
std::cout << "CFoo() copy constructor called." << std::endl;
}
CFoo(CFoo&& other )
: m_value(std::move(other.m_value))
{
std::cout << "CFoo() move constructor called." << std::endl;
std::cout << "other.m_value = " << other.m_value.c_str() << std::endl;
}
~CFoo()
{
std::cout << "~CFoo() called." << std::endl;
}
const CFoo& operator=( const CFoo& other )
{
std::cout << "CFoo copy assignment operator called." << std::endl;
if( &other != this )
{
m_value = other.m_value;
}
return *this;
}
const CFoo& operator=( CFoo&& other )
{
std::cout << "CFoo move assignment operator called." << std::endl;
if( &other != this )
{
m_value = std::move(other.m_value);
}
return *this;
}
CFoo ToUpper()
{
return CFoo(::ToUpper(m_value));
}
CFoo ToLower()
{
return CFoo(::ToLower(m_value));
}
const char * ToString() const
{
return m_value.c_str();
}
};
int main( int argc, const char *argv[] )
{
{
CFoo foo;
CFoo foo1("Hello World");
CFoo foo2 = CFoo("Hello again World!");
CFoo foo3(CFoo("Bye world"));
CFoo foo4 = CFoo("Bye again world");
CFoo foo5 = foo4.ToUpper();
CFoo foo6 = foo4.ToLower();
foo6 = foo4.ToUpper();
std::cout << "foo4: " << foo4.ToString() << std::endl;
foo6 = CFoo("Well well well");
}
return 0;
}
My apologies if the code is not as short as it might possibly be. But there are only a few spots to look at, namely my efforts to get the move constructor invoked in main() and the definition of the various constructors in class Foo.
I am aware of compiler settings which allow turning off RVO and stuff but for the purpose of using the feature "move constructor" in performance aware code, there should be a classic example of when it gets invoked. If that is not the case, I will probably decide not to even bother using move constructors at all.
To answer the question, you can tell me a line I can write in main() which gets the move constructor of CFoo called. Or you can tell me what I am doing wrong.
Does std::string support being moved like that? Maybe this is why my efforts fail?
Thanks, in advance.

In all your attempts to use the move constructor it is being elided, so that e.g. CFoo foo = CFoo(blah); is simply equivalent to CFoo foo(blah); which doesn't need to use the move constructor. This is a Good Thing because the compiler is optimising away the need for any copy or move to happen at all.
To see the move constructor being used try:
CFoo f1;
CFoo f2 = std::move(f1);
This constructs f2 from an rvalue, and nothing can be elided, so the move constructor will be used.

First of all, there is an error in std::string ToUpper(const std::string& s), namely there is no space in result. C++ algorithms do not grow their target containers automatically. You must either allocate space yourself, or use a inserter adaptor.
To make space in out, e.g. do this:
result.resize(s.length());
After it the move assignment operator called for:
foo6 = foo4.ToUpper();
foo6 = CFoo("Well well well");
The move constructor is called whenever an object is initialized from xvalue of the same type, which includes:
initialization, T a = std::move(b); or T a(std::move(b));, where b is of type T
function argument passing: f(std::move(a));, where a is of type T and f is void f(T t)
function return: return a; inside a function such as T f(), where a is of type T which has a move constructor.
For more see move constructors on cppreference.com.

Related

Is there a useful scenario for moving const objects?

I realized that the common-knowledge that "you cannot move a const object" is not entirely true. You can, if you declare the move ctor as
X(const X&&);
Full example below:
#include <iostream>
struct X
{
X() = default;
X(const X&&) {std::cout << "const move\n";}
};
int main()
{
const X x{};
X y{std::move(x)};
}
Live on Coliru
Question: is there any reason why one would want such a thing? Any useful/practical scenario?
Your example doesn't move anything. Yes, you wrote std::move to get an rvalue and you invoked a move constructor, but nothing actually ends up getting moved. And it can't, because the object is const.
Unless the members you were interested in were marked mutable, you would not be able to do any "moving". So, there is no useful or even possible scenario.
Not sure whether it's practical, but it can be made legal provided the modified data members are mutable.
This program is legal, and if you like that kind of thing, would easily become hard to follow:
#include <iostream>
#include <string>
struct animal
{
animal(const animal&& other) : type(other.type) {
other.type = "dog";
}
animal() = default;
mutable std::string type = "cat";
};
std::ostream& operator<<(std::ostream& os, const animal& a)
{
return os << "I am a " << a.type;
}
std::ostream& operator<<(std::ostream& os, const animal&& a)
{
return os << "I am a " << a.type << " and I feel moved";
}
int main()
{
const auto cat = animal();
std::cout << cat << std::endl;
auto dog = std::move(cat);
std::cout << cat << std::endl;
std::cout << dog << std::endl;
std::cout << std::move(dog) << std::endl;
}
expected output:
I am a cat
I am a dog
I am a cat
I am a cat and I feel moved
As the comments have noted, you cannot actually "move" anything out of the argument object, because it is const (at least, not without a const cast, which is a bad idea as it could lead to UB). So it's clearly not useful for the sake of moving. The entire purpose of move semantics is to provide a performance optimization, and that is not happening here, so why do it?
That said, I can only think of two cases where this is useful. The first involves "greedy" constructors:
#include <iostream>
struct Foo {
Foo() = default;
Foo(const Foo&) { std::cerr << "copy constructor"; }
Foo(Foo&&) { std::cerr << "copy constructor"; }
template <class T>
Foo(T&&) { std::cerr << "forward"; }
};
const Foo bar() { return Foo{}; }
int main() {
Foo f2(bar());
return 0;
}
This program prints "forward". The reason why is because the deduced type in the template will be const Foo, making it a better match. This also shows up when you have perfect forwarding variadic constructors. Common for proxy objects. Of course returning by const value is bad practice, but strictly speaking it's not incorrect, and this may break your class. So you should really provide a Foo(const Foo&&) overload (which just delegates to the copy constructor); think of it as crossing a t or dotting an i when you are writing high quality generic code.
The second case occurs when you want to explicitly delete move constructors, or a move conversion operator:
struct Baz {
Baz() = default;
Baz(const Baz&) = default;
Baz(Baz&&) = delete;
};
const Baz zwug() { return {}; }
int main() {
Baz b2(zwug());
}
This program compiles so the author failed at their mission. The reason why is because const ref overloads match against const rvalues, and const rvalue construction was not explicitly deleted. If you want to delete moves you'll need to delete the const rvalue overload too.
The second example may seem wildly obscure but say you are writing a class that provides a view of a string. You may not want to allow it to be constructed from a string temporary, since you are at greater risk of the view being corrupted.

Can a const object, returned by value, still be moved?

Example:
Foo return_a_foo()
{
const auto a_foo = make_a_foo();
//Work with, but do not mutate a_foo...
return a_foo;
}
If the compiler cannot employ RVO, I'd at least expect it to try and move a_foo. However, a_foo is const (but still about to go out of scope). Does it say anywhere in the standard that this is 100% guaranteed not to move (bummer) or is it implementation defined ?
Can a const object, returned by value, still be moved?
Some will be shocked to learn that the answer is, "sometimes, yes".
However, you have to give them more constructors in order to enable this. You would also have to either make members mutable or otherwise manually handle const-move-construction.
Proof:
#include <iostream>
#include <memory>
struct Foo
{
Foo() { std::cout << "default c'tor\n"; }
Foo(Foo const&&) { std::cout << "Foo const&&\n"; }
Foo(Foo &&) { std::cout << "Foo &&\n"; }
Foo(Foo const&) { std::cout << "Foo const&\n"; }
Foo(Foo &) { std::cout << "Foo &\n"; }
};
const Foo make_a_foo()
{
auto p = std::make_unique<const Foo>();
return std::move(*p);
}
const Foo return_a_foo()
{
const auto a_foo = make_a_foo();
//Work with, but do not mutate a_foo...
return a_foo;
}
int main()
{
auto f = return_a_foo();
}
example output:
default c'tor
Foo const&&
No, a const T can't be bound to a non-const T&&, so a_foo can't be moved from.
Your function returns a non-const Foo though, so a_foo will be copied to the return value. The return value can then be moved from, since it's non-const. See this example.
In reality all of those copies and moves will likely be elided.

std::move used, move constructor called but object still valid

Can someone explain why the original object that is passed to a new object via std::move is still valid afterwards?
#include <iostream>
class Class
{
public:
explicit Class(const double& tt) : m_type(tt)
{
std::cout << "defaultish" << std::endl;
};
explicit Class(const Class& val) :
m_type(val.m_type)
{
std::cout << "copy" << std::endl;
};
explicit Class(Class&& val) :
m_type(val.m_type)
{
m_type = val.m_type;
std::cout << "move: " << m_type << std::endl;
};
void print()
{
std::cout << "print: " << m_type << std::endl;
}
void set(const double& tt)
{
m_type = tt;
}
private:
double m_type;
};
int main ()
{
Class cc(3.2);
Class c2(std::move(cc));
c2.print();
cc.set(4.0);
cc.print();
return 0;
}
It outputs the following:
defaultish
move: 3.2
print: 3.2
print: 4
I would expect the calls to cc.set() and cc.print() to fail...
UPDATE
Thanks to answers below, we've identified that 1) I wasn't moving anything in the move constructor, and 2) std::move() on an int or double doesn't do anything because it's more expensive to move these types than to simply copy. The new code below updates the class's private member variable to be of type std::string instead of a double, and properly calls std::move when setting this private member variable in the Class' move constructor, resulting in an output that shows how a std::move results in a valid but unspecified state
#include <iostream>
#include <string>
class Class
{
public:
explicit Class(const std::string& tt) : m_type(tt)
{
std::cout << "defaultish" << std::endl;
};
explicit Class(const Class& val) :
m_type(val.m_type)
{
std::cout << "copy" << std::endl;
};
explicit Class(Class&& val) : m_type(std::move(val.m_type))
{
std::cout << "move: " << m_type << std::endl;
};
void print()
{
std::cout << "print: " << m_type << std::endl;
}
void set(const std::string val )
{
m_type = val;
}
private:
std::string m_type;
};
int main ()
{
Class cc("3.2");
Class c2(std::move(cc));
c2.print( );
cc.print();
cc.set( "4.0" );
cc.print();
return 0;
}
And finally the output:
defaultish
move: 3.2
print: 3.2
print:
print: 4.0
Because the standard says so.
Moved-from objects have a valid but unspecified state. That means you can still use them, but you can't be sure what state they'll be in. They could look just as they did before the move, depending on what is the most efficient way to "move" data out of them. For example, "moving" from an int makes no sense (you'd have to do extra work to reset the original value!) so a "move" from an int is actually only ever going to be a copy. The same is true of a double.
Although in this case it's got more to do with the fact that you didn't actually move anything.
In the code example, std::move determines which constructor gets called. Nothing more. So c2(std::move(cc)) calls the move constructor for Class. The move constructor for Class doesn't do anything to its argument, so cc is unchanged, and it can be used just as it could have before the call to the move constructor.
All the talk in comments and answers about the state of an object that has been moved from is about the requirements on standard library types, which will be left in a "valid but unspecified state" (17.6.5.15, [lib.types.movedfrom]). What you do with your types is not affected by that.
EDIT: sigh. You edited the code and changed the question. Now that your class holds a std::string instead of a float things are different, and the std::string object in cc is, indeed, in a "valid but unspecified state".

How do I prevent code repeat between rvalue and lvalue member functions?

For the program code below, I have to write the the same code inside the pair of member functions which receiving rvalue and lvalue references.
My aim is to use only one from the pair (e.g.; only use the rvalue accepting ones), and the others. I read the reference of std::forward, as far as I understood, it looks like it is for this purpose. But, when I delete the lvalue reference taking ones, I get the following compiler error.
'TestClass::TestClass(const TestClass &)': cannot convert argument 1 from 'std::wstring' to 'std::wstring &&'
How do I prevent this code duplication?
#include <iostream>
#include <string>
class TestClass
{
public:
TestClass(const std::wstring & Text)
: Text(Text)
{
std::wcout << L"LValue Constructor : " << Text << std::endl;
/*Some code here...*/
}
TestClass( std::wstring && Text)
: Text(std::forward<std::wstring>(Text))
{
std::wcout << L"RValue Constructor : " << this->Text << std::endl;
/*Same code here...*/
}
TestClass(const TestClass & Another)
: Text(Another.Text)
{
std::wcout << L"Copy Constructor : " << Text << std::endl;
/*Some code here...*/
}
TestClass( TestClass && Another)
: Text(std::forward<std::wstring>(Another.Text))
{
std::wcout << L"Move Constructor : " << Text << std::endl;
/*Same code here...*/
}
private:
std::wstring Text;
};
int wmain(int argc, wchar_t *argv[], wchar_t *envp[])
{
std::wstring Argument(L"Testing Copy");
TestClass Class1Copy(Argument);
TestClass Class1Move(L"Testing Move");
TestClass Class2Copy(Class1Copy);
TestClass Class2Move(std::move(Class1Move));
_wsystem(L"pause");
return 0;
}
Output:
LValue Constructor : Testing Copy
RValue Constructor : Testing Move
Copy Constructor : Testing Copy
Move Constructor : Testing Move
Press any key to continue . . .
If move construction is expected to be extremely cheap, you can take by value and move-from the value. This does exactly 1 more move than a pair of copy and move overloads.
If you want optimal efficiency, and/or if move construction is cheaper but not cheap enough to neglect, you can forward:
template<class T>
std::decay_t<T> copy(T&& t) {
return std::forward<T>(t);
}
class TestClass {
public:
TestClass(std::wstring const& Text)
TestClass( copy(Text) )
{}
TestClass(TestClass const& o)
: TestClass( o.Text )
{}
TestClass(TestClass&& o)
: TestClass( std::move(o).Text ) // pattern does the right thing more often than `std::move(o.Text)` does.
{}
// only "real" ctor:
TestClass( std::wstring&& Text)
: Text(std::forward<std::wstring>(Text))
{
std::wcout << L"RValue Constructor : " << this->Text << std::endl;
/*Code here...*/
}
// ...
now everything forwards down to the one constructor.
You can even mix the two techniques: use by-value for std::wstring (as we know that is cheap-to-move) and do forwarding stuff for the TestClass code (or anything less likely to be stable).
You can take by value and then move. Then you only need N overloads, not 2N:
TestClass(std::wstring Text)
: Text(std::move(Text))
{
}
You can avoid the copy constructor and move constructor duplication by writing nothing at all; the compiler will generate them by default in this case.
I don't think you can do that since the function's signatures determine when and where they are used. It's like a copy constructor and an assignment operator. They do somewhat similar things but the compiler calls the appropriate one basee on context.
If you want to avoid reusing code, just factor out the commonality into a separate function.

C++ const std::string assignment

What is most appropriate in const std::string assignment/declaration? Using the constructor(e.g., const std::string WORD("hello");) or using equal operator(e.g., const std::string WORD= "hello";)?
Does these things has difference in memory usage or time processes?
For any reasonable compiler, the code generated will be the same in both cases. Whether you should use direct initialization or copy-initialization in this case is essentially opinion-based.
In both cases, generally compilers will remove the copies using "Return Value Optimisation" anyway. See this code on ideone here calls neither the ordinary constructor nor the assignment operator as it doesn't print that they're being called to screen:
That is:
#include <iostream>
class C
{
public:
C() {}
C(const char[]) { std::cout << "Ordinary Constructor" << std::endl; }
C& operator=(const char[]) { std::cout << "Assignment Operator" << std::endl; return *this; }
};
int main() {
std::cout << "Start" << std::endl;
C x1 = "Hello";
C x2("Hello");
std::cout << "End" << std::endl;
}
Simply outputs:
Start
End
It doesn't output:
Start
Assignment Operator
Ordinary Constructor
End
As C++ allows the copies to be skipped and the temporary to be constructed in place.
The lines:
std::string x = "hello";
std::string x("hello");
both will only call the constructor of std::string. That is, they are identical, and neither will use the operator= overloads.