Intel® C++ Compiler
Community support and assistance for creating C++ code that runs on platforms based on Intel® processors.

Intel Compiler 17.0u3 not calling move constructor

AndrewC
New Contributor III
651 Views

On Windows, I have some fairly straightforward move constructors defined for some matrix classes.

One would expect the move constructor to be called when the object is returned from the example function below -  and it is when compiled with Visual C++ 2015 update 3. When compiled with Intel 17u3, the behaviour is bizarre. Neither the move constructor OR the copy constructor are called.Everything is compiled in DEBUG mode,IPO is off. I can understand that perhaps the compiler can be clever when all optimizations are on, but this is with all optimizations off.

 

Visual C++ 2015 output

constructor 1:FloatSymMat
move constructor:FloatSymMat
destructor:~FloatSymMat
about to call std::move
move constructor:FloatSymMat
destructor:~FloatSymMat
destructor:~FloatSymMat

Intel C++ output

constructor 1:FloatSymMat
about to call std::move
move constructor:FloatSymMat
destructor:~FloatSymMat
destructor:~FloatSymMat

If I EXPLICITLY call

FloatSymMat tmp_mat = std::move(symmat);

Then the move constructor is called as expected.

// testmoveconstructor.cpp : Defines the entry point for the console application.
//

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

inline unsigned SymMatSize(unsigned n) { return n*(n + 1) / 2; }

class  FloatSymMat {
private:

	std::vector<float> vec;
	unsigned n;
	// The data which define the matrix


public:
	FloatSymMat();
	FloatSymMat(const FloatSymMat&);
	FloatSymMat(FloatSymMat&&)noexcept;
	FloatSymMat(unsigned n, unsigned nAgain);
	FloatSymMat(unsigned n, unsigned nAgain, float initval);
	~FloatSymMat();
};



FloatSymMat::FloatSymMat(unsigned M, unsigned N)
	: vec(SymMatSize(N), 0)
{
	cout << "constructor 1:" << __func__ << endl;
	n = N;
}

FloatSymMat::FloatSymMat(unsigned M, unsigned N, float initval)
	: vec(SymMatSize(N), initval)
{
	cout << "constructor 2:" << __func__ << endl;
	n = N;
}

inline FloatSymMat::~FloatSymMat()
{
	cout << "destructor:" << __func__ << endl;
}

inline FloatSymMat::FloatSymMat()
	: vec()
{
	cout << "default constructor:" << __func__ << endl;
	n = 0;
}

inline FloatSymMat::FloatSymMat(const FloatSymMat& A)
	: vec(A.vec)
{
	cout << "copy constructor:" << __func__ << endl;
	n = A.n;
}



inline FloatSymMat::FloatSymMat(FloatSymMat&& A)noexcept
	: vec(std::move(A.vec))
{
	cout << "move constructor:" << __func__ << endl;
	n = A.n;
	A.n = 0;
}


FloatSymMat testReturn()
{
	FloatSymMat symmat(3, 3);
	return symmat;
}


int main()
{
	FloatSymMat tmp = testReturn();
	cout << "about to call std::move" << endl;
	FloatSymMat tmp_mat = std::move(tmp);
	return 0;
}

 

 

0 Kudos
1 Solution
Bastian_B_
New Contributor I
651 Views

http://en.cppreference.com/w/cpp/language/copy_elision ?

Keywords to look for are RVO (Return Value Optimization) and NRVO (Named Return Value Optimization).

View solution in original post

0 Kudos
4 Replies
AndrewC
New Contributor III
651 Views

One additional comment - I can understand if the compiler is doing something very smart here - as the code seems to function as expected - but I am a bit baffled.

Also, anyone working through  a C++ move constructor tutorial will get really confused!

0 Kudos
Bastian_B_
New Contributor I
652 Views

http://en.cppreference.com/w/cpp/language/copy_elision ?

Keywords to look for are RVO (Return Value Optimization) and NRVO (Named Return Value Optimization).

0 Kudos
AndrewC
New Contributor III
651 Views

Very interesting and that explains it.  Is the RVO  controlled by any optimization switch on the compiler or is it always on by default?

0 Kudos
Judith_W_Intel
Employee
651 Views

 

Return value optimization is on by default.

0 Kudos
Reply