「这是我参与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 次。