Move constructor problem Visual2010

Hello

I create a class with a move constructor as followed:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
#include <string>
using namespace std;

class Base{
public:
	Base(const string& str):m_Str(str)	
		{cout << m_Str << ": Use COPY constructor \n";};
	Base(string&& str):m_Str(move(str))
		{cout << m_Str <<": Use MOVE constructor \n";};	
private:
	string m_Str;
};

int main(int argc, char* argv[])
{
	Base b("example");
	system("pause");
	return 0;

}


However when I create the object "b" the COPY constructor is used.
When I write instead:

Base b((string)"example");

then the it works, the MOVE constructor is used. The problem may be linked to the conversion of char array and string...

Anyone know where lies the problem? I do not have this problem with VS2012 but my company uses VS2010. Thank you.
Last edited on
looks like VS2010 does not support implicit moving of implicitly created l-value variables.
Techncally even Base b((string)"example"); may use copy constructor. to be sure that move constructor is used use std::move() with argument.

EDIT: http://blogs.msdn.com/b/vcblog/archive/2011/09/12/10209291.aspx
Look under R-value references section. It describes it.
Last edited on
> I do not have this problem with VS2012

VS 2012 is right.

Base b("example"); is direct initialization
http://en.cppreference.com/w/cpp/language/direct_initialization

T object ( arg ); (1) initialization with a nonempty parenthesized list of expressions
...
The effects of direct initialization are:
If T is a class type, the constructors of T are examined and the best match is selected by overload resolution. The constructor is then called to initialize the object.
...
... direct-initialization considers all constructors and implicit conversion sequences.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>
#include <string>
#include <utility>
using namespace std;

class Base{
public:
    Base(const string& str):m_Str(str)
		{cout << m_Str << ": Use COPY constructor \n";};
	Base(string&& str):m_Str(move(str))
		{cout << m_Str <<": Use MOVE constructor \n";};
private:
	string m_Str;
};

int main()
{
	Base b("example"); // direct initialization: Use MOVE constructor

        // http://en.cppreference.com/w/cpp/language/copy_initialization
	Base b2 = string("second example") ; // copy initialization: Use MOVE constructor

        // copy initialization is less permissive than direct initialization
	// Base b3 = "third example" ; // *** error
}

http://coliru.stacked-crooked.com/a/c215d28ffae2a184

Ideally, user-defined move constructors should not throw
Base(string&& str) noexcept( is_nothrow_move_constructible<string>::value ) ;
See: http://en.cppreference.com/w/cpp/utility/move_if_noexcept


> Techncally even Base b((string)"example"); may use copy constructor.

No. Not if Base::Base( string&& ) is accessible.
Last edited on
Thank you a lot for your reply

Canh
I'm sorry, I should have mentioned this earlier.

Even though we are printing "Use MOVE constructor", and have loosely referred to the constructor that moves a string as the 'move constructor',

technically the move constructor is the implicitly defined Base( Base&& other )noexcept ;
http://en.cppreference.com/w/cpp/language/move_constructor

Base( string&& str ) /* noexcept */ is just a constructor that takes an rvalue reference to a string.
Last edited on
Topic archived. No new replies allowed.