过去几天我一直在学习(N)RVO。正如我在复制文章中读到的cppreference,对于C ++ 14:
...允许编译器,但不要求省略复制和移动(自C ++ 11)类对象的构造,即使复制/移动(自C ++ 11)构造函数和析构函数有可观察到的副作用。这是一个优化:即使它发生并且没有调用 copy- / move-constructor ,它仍然必须存在并且可访问(就好像没有优化发生在所有),否则该程序是不正确的。
因此,复制或移动构造函数必须存在且可访问。但是在下面的代码中:
#include <iostream>
class myClass
{
public:
myClass() { std::cout << "Constructor" << std::endl; }
~myClass() { std::cout << "Destructor" << std::endl; }
myClass(myClass const&) { std::cout << "COPY constructor" << std::endl;}
myClass(myClass &&) = delete;
};
myClass foo()
{
return myClass{};
}
int main()
{
myClass m = foo();
return 0;
}
我收到以下错误:test.cpp: In function 'myClass foo()':
test.cpp:15:17: error: use of deleted function 'myClass::myClass(myClass&&)'
return myClass{};
。即使我没有从foo()
拨打main()
,我也会收到此错误消息。与NRVO相同的问题。
因此,移动构造函数总是必需的,不是吗? (虽然副本不是,我检查了一下)
我不明白编译器需要移动构造函数的位置。我唯一的猜测是它可能需要构造一个临时变量,但这听起来很值得怀疑。有人知道答案吗?
关于编译器:我在g ++和VS编译器上试过它,你可以在线查看:http://rextester.com/HFT30137。
P.S。我知道在C ++ 17标准中,RVO是有义务的。但是NRVO并不是,所以我想研究一下这里发生了什么,以便了解何时可以使用NRVO。
答案 0 :(得分:6)
引自cppreference:
已删除的功能
如果,而不是函数体,特殊语法=删除;使用时,该函数被定义为已删除。
...
如果函数超载,则首先进行重载解析,如果选择了已删除的函数,则程序只会格式错误。
如果明确定义要删除的移动构造函数,那就不一样了。这里由于存在这个删除的移动构造函数,虽然复制构造函数可以匹配,但移动构造函数更好,因此在重载解析期间选择了移动构造函数。
如果删除显式@Override
public View getView(int position, View convertView, ViewGroup parent) {
View row;
ViewHolder holder;
if (convertView == null) {
LayoutInflater inflater = LayoutInflater.from(mContext);
row = inflater.inflate(mLayoutResourceId, parent, false);
holder = new ViewHolder(row);
row.setTag(holder);
} else {
row = convertView;
holder = (ViewHolder) row.getTag();
}
Order orders = mData[position];
holder.nameOfSchool.setText(orders.nameOfSchool);
holder.nameOfAgent.setText(String.valueOf(orders.nameOfAgent));
holder.orderId.setText(String.valueOf(orders.orderId));
holder.netRevenue.setText(String.valueOf(orders.netRevenue));
holder.orderQuantity.setText(String.valueOf(orders.totalQuantity));
holder.date.setText(String.valueOf(orders.date));
return row;
}
,则会选择复制构造函数并编译程序。