Vit*_*meo 90 c++ constructor default move-semantics c++11
这是
struct Example {
int a, b;
Example(int mA, int mB) : a{mA}, b{mB} { }
Example(const Example& mE) : a{mE.a}, b{mE.b} { }
Example(Example&& mE) : a{move(mE.a)}, b{move(mE.b)} { }
Example& operator=(const Example& mE) { a = mE.a; b = mE.b; return *this; }
Example& operator=(Example&& mE) { a = move(mE.a); b = move(mE.b); return *this; }
}
Run Code Online (Sandbox Code Playgroud)
相当于此
struct Example {
int a, b;
Example(int mA, int mB) : a{mA}, b{mB} { }
Example(const Example& mE) = default;
Example(Example&& mE) = default;
Example& operator=(const Example& mE) = default;
Example& operator=(Example&& mE) = default;
}
Run Code Online (Sandbox Code Playgroud)
?
Pie*_*aud 46
是的,两者都是一样的.
但
struct Example {
int a, b;
Example(int mA, int mB) : a{mA}, b{mB} { }
Example(const Example& mE) = default;
Example(Example&& mE) = default;
Example& operator=(const Example& mE) = default;
Example& operator=(Example&& mE) = default;
}
Run Code Online (Sandbox Code Playgroud)
此版本将允许您跳过正文定义.
但是,在声明时必须遵循一些规则explicitly-defaulted-functions:
8.4.2明确违约的函数[dcl.fct.def.default]
表单的函数定义:
Run Code Online (Sandbox Code Playgroud)attribute-speci?er-seqopt decl-speci?er-seqopt declarator virt-speci?er-seqopt = default ;被称为明确默认的定义.明确默认的函数应该
是一个特殊的会员功能,
具有相同的声明函数类型(可能不同的ref限定符除外,在复制构造函数或复制赋值运算符的情况下,参数类型可能是"引用非const
T",其中T是成员函数的名称)如同隐含声明的那样,没有默认参数.
Sha*_*our 19
是的,默认的移动构造函数将执行其基础和成员的成员移动,因此:
Example(Example&& mE) : a{move(mE.a)}, b{move(mE.b)} { }
Run Code Online (Sandbox Code Playgroud)
相当于:
Example(Example&& mE) = default;
Run Code Online (Sandbox Code Playgroud)
我们可以通过转到草案C++ 11标准部分12.8 复制和移动类对象第13段来看到这一点(强调我的未来):
被默认并为已删除不限定的复制/移动的构造 隐含定义如果odrused(3.2)或当它在其第一声明之后显式默认值.[注意:即使实现省略了odr-use(3.2,12.2),也会隐式定义复制/移动构造函数. - 注意事项] [...]
和第15段说:
非联合类X 的隐式定义的复制/移动构造函数执行其基础和成员的成员复制/移动.[注意:忽略非静态数据成员的大括号或大小写.另请参见12.6.2中的示例.-end note]初始化顺序与用户定义构造函数中基数和成员的初始化顺序相同(见12.6.2).设x是构造函数的参数,或者对于移动构造函数,x是引用参数的xvalue.以适合其类型的方式复制/移动每个基本或非静态数据成员:
- 如果成员是一个数组,则使用x的相应子对象直接初始化每个元素;
- 如果成员m具有右值引用类型T &&,则使用static_cast(xm)进行直接初始化;
- 否则,用x的相应基数或成员直接初始化基数或成员.
虚拟基类子对象只能由隐式定义的复制/移动构造函数初始化一次(见12.6.2).
是一个
=default移动的构造相当于一个成员明智之举构造?
是的。更新:嗯,并非总是如此。看这个例子:
#include <iostream>
struct nonmovable
{
nonmovable() = default;
nonmovable(const nonmovable &) = default;
nonmovable( nonmovable &&) = delete;
};
struct movable
{
movable() = default;
movable(const movable &) { std::cerr << "copy" << std::endl; }
movable( movable &&) { std::cerr << "move" << std::endl; }
};
struct has_nonmovable
{
movable a;
nonmovable b;
has_nonmovable() = default;
has_nonmovable(const has_nonmovable &) = default;
has_nonmovable( has_nonmovable &&) = default;
};
int main()
{
has_nonmovable c;
has_nonmovable d(std::move(c)); // prints copy
}
Run Code Online (Sandbox Code Playgroud)
它打印:
copy
Run Code Online (Sandbox Code Playgroud)
http://coliru.stacked-crooked.com/a/62c0a0aaec15b0eb
您声明了默认的move构造函数,但复制而不是移动。为什么?因为如果一个类甚至只有一个不可移动的成员,那么显式默认的 move构造函数将被隐式删除(例如,双关语)。因此,当您运行时has_nonmovable d = std::move(c),实际上会调用copy构造函数,因为has_nonmovable(隐式地)删除了move构造函数,所以它实际上不存在(即使您通过expression显式声明了move构造函数has_nonmovable(has_nonmovable &&) = default)。
但是,如果non_movable根本不声明的move构造函数,则将将move构造函数用于movable(以及每个具有move构造函数的成员),将将copy构造函数用于nonmovable(以及每个未定义move构造函数的成员) )。参见示例:
#include <iostream>
struct nonmovable
{
nonmovable() = default;
nonmovable(const nonmovable &) { std::cerr << "nonmovable::copy" << std::endl; }
//nonmovable( nonmovable &&) = delete;
};
struct movable
{
movable() = default;
movable(const movable &) { std::cerr << "movable::copy" << std::endl; }
movable( movable &&) { std::cerr << "movable::move" << std::endl; }
};
struct has_nonmovable
{
movable a;
nonmovable b;
has_nonmovable() = default;
has_nonmovable(const has_nonmovable &) = default;
has_nonmovable( has_nonmovable &&) = default;
};
int main()
{
has_nonmovable c;
has_nonmovable d(std::move(c));
}
Run Code Online (Sandbox Code Playgroud)
它打印:
movable::move
nonmovable::copy
Run Code Online (Sandbox Code Playgroud)
http://coliru.stacked-crooked.com/a/420cc6c80ddac407
更新:但是,如果您注释掉该行has_nonmovable(has_nonmovable &&) = default;,则两个成员都将使用副本:http : //coliru.stacked-crooked.com/a/171fd0ce335327cd-打印:
movable::copy
nonmovable::copy
Run Code Online (Sandbox Code Playgroud)
因此,将其放到=default任何地方仍然很有意义。这并不意味着您的移动表达式将始终移动,但是这样做的机会更高。
再进行一次更新:但是如果将has_nonmovable(const has_nonmovable &) = default;其中任一行注释掉,那么结果将是:
movable::move
nonmovable::copy
Run Code Online (Sandbox Code Playgroud)
因此,如果您想知道程序中会发生什么,只需自己做所有事情即可:
| 归档时间: |
|
| 查看次数: |
25125 次 |
| 最近记录: |