RVO和删除的C ++ 14中的移动构造函数

时间:2018-02-03 19:12:24

标签: c++ c++14 move-constructor

过去几天我一直在学习(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。

1 个答案:

答案 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; } ,则会选择复制构造函数并编译程序。