拷贝构造优化问题

68 阅读2分钟

「这是我参与2022首次更文挑战的第23天,活动详情查看:2022首次更文挑战

class widget
{
public:
	widget() 	     
	{}
	widget(const widget& w)
	{
		cout << "widget(const widget& w)" << endl;
	}
	widget& operator=(const widget& w)
	{
		cout << "widget& operator=(const widget& w)" << endl;
		return *this;
	}
	~widget()
	{}
};
void f1(widget w)
{}
widget f2()
{
	widget W;
	return W;
}
int main()
{
  	widget w1;
	//传值传参和传值返回都会生成一个拷贝对象
	f1(w1);
	f2();
	//本来应该是两次拷贝构造,但是这种情况下编译器会优化
	widget ret = f2();
	
	//不会优化
	/*widget ret;
	ret = f2();*/
	
	return 0;
}

📝说明

❓ 传返回值拷贝构造优化问题 ❔

在这里插入图片描述 匿名对象 ❓

我们定义对象除了常规的方式还可以定义匿名对象,匿名对象没有名字,它的生命周期只在这一行 。

widget w;

widget(); 

比如当只想调用 Print 时就会使用匿名对象。

widget w;
w.Print();

widget().Print();

❓ 传参数也是类似的 ❔

class widget
{
public:
	widget() 	     
	{
		cout << "widget" << endl;
	}
	widget(const widget& w)
	{
		cout << "widget(const widget& w)" << endl;
	}
	~widget()
	{
		cout << "~widget()" << endl;	
	}
};
void f1(widget w)
{}
int main()
{
	//先构造,再去拷贝构造,这是正常的写法,编译器没有任何的优化
	/*widget w;
	f1(w);*/
	
	//传参匿名对象
	f1(widget());
	
	return 0;
}

📝说明

传匿名对象优化问题 ❓

本来应该是构造和拷贝构造,但是编译器做了优化。

💨总结

VS2017 中在传值传参和传值传返回值的过程中,只要是在一个表达式调用的连续步骤中:拷贝构造、拷贝构造,两次会被优化成一次; 构造、拷贝构造,会被编译器优化合并成构造。

❓ 以下代码共调用多少次拷贝构造函数 ❔

Widget f(Widget u)
{
	Widget v(u);
	Widget w = v;
	return w;
}
main()
{
	Widget x;
	Widget y = f(f(x));
}

📝 说明

在这里插入图片描述 所以总共拷贝构造了 7 次。