mor*_*rte 1 c++ move-semantics c++11 c++14
来自N3337:
如果类X的定义没有显式地声明一个移动构造函数,那么当且仅当一个移动构造函数被隐式声明为默认值时
X没有用户声明的复制构造函数,X没有用户声明的复制赋值运算符,X没有用户声明的移动赋值运算符,X没有用户声明的析构函数,并且移动构造函数将不要隐式定义为已删除.
第一个问题是:为什么编译器在不应该生成移动构造函数时(存在用户声明的析构函数和其他阻止生成移动构造函数的函数).下面的示例程序打印constructorCounter=5表示使用了移动构造函数(没有移动操作值:: constructorCounter应该是10)
#include <iostream>
class value {
public:
value() {
++constructorCounter;
}
value(const int value)
: _value(value)
{
++constructorCounter;
}
value(const value& other)
: _value(other._value)
{
++constructorCounter;
}
const value& operator=(const value& rhs) {
_value = rhs._value;
return _value;
}
~value() { }
static int constructorCounter;
private:
int _value;
};
int value::constructorCounter = 0;
class array {
public:
// array() = delete;
// array(array&&) = delete;
array(const int size)
: _size(size), _values(new value[size])
{
std::clog << "array(const int size)" << std::endl;
}
array(const array& rhs)
: array(rhs._size)
{
std::clog << "array(const array& rhs)" << std::endl;
for (int i = 0; i < _size; ++i)
_values[i] = rhs._values[i];
}
array& operator=(const array&) {
std::clog << "array& operator=(const array&)" << std::endl;
}
~array() {
delete [] _values;
}
private:
value* _values;
int _size;
};
int main(int argc, char *argv[]) {
array c(array(5));
std::clog << "constructor counter=" << value::constructorCounter << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
第二个相关的问题:为什么程序无法编译,如果我禁用移动constructor array(array&&) = deleted;,为什么没有"后退"复制consturctor array(const array&)?
Rer*_*ito 10
首先,行:
array c(array(5));
Run Code Online (Sandbox Code Playgroud)
导致使用的复制构造函数(因为没有用户声明的移动构造函数).但是,由于它恰好是c对象构造,编译器能够忽略副本并array就地构造对象.
现在,当您将移动构造函数用户声明为delete-d时,会在重载解析期间以及在解析行调用时将其视为:
array c(array(5));
Run Code Online (Sandbox Code Playgroud)
array(array&&) 将是一个完美的匹配...但它被删除,所以重载决议停止(完美匹配),并输出错误(该功能被删除).
正如评论中所建议的那样,您是否一直在使用C++ 17标准进行编译
array c(array(5));
Run Code Online (Sandbox Code Playgroud)
因为它符合以下情况,所以会产生有保证的复制省略:
在初始化中,如果初始化表达式是prvalue且源类型的cv-nonqualified版本与目标类相同,则初始化表达式用于初始化目标对象
渲染代码严格等同于:
array c(5);
Run Code Online (Sandbox Code Playgroud)