C++11 赋值运算符的Sink参数实现及语言缺陷
Sean Parent在2012年C++now大会上的重点演讲中介绍了“sink参数”的概念。他的建议是,如果参数被函数“消耗”,则按值传递参数。然后根据其R值或L值移动或复制sink参数 他明确提到赋值运算符是具有sink参数的操作的一个实例 因此,他在演讲中以这一实施为例:C++11 赋值运算符的Sink参数实现及语言缺陷,c++11,move-semantics,assignment-operator,C++11,Move Semantics,Assignment Operator,Sean Parent在2012年C++now大会上的重点演讲中介绍了“sink参数”的概念。他的建议是,如果参数被函数“消耗”,则按值传递参数。然后根据其R值或L值移动或复制sink参数 他明确提到赋值运算符是具有sink参数的操作的一个实例 因此,他在演讲中以这一实施为例: object_t& operator = (object_t x) { object_ = move(x.object_); return *this; } 在随后的会谈中,例如在2013年Gong Nati
object_t& operator = (object_t x)
{ object_ = move(x.object_); return *this; }
在随后的会谈中,例如在2013年Gong Native大会上,他重复了指南,但提到由于语言缺陷,需要实施单独的移动分配操作员:
这是他幻灯片中的引文:
- 为每个值传递接收器参数,并将其移动或交换到位
- sink参数是函数传递的任何参数。
- 赋值的参数是sink参数
- 但是,由于语言缺陷,必须编写移动分配运算符
约阿希姆(Joachim)肖恩(Sean)的父母在他的评论中回答了这个问题
假设您有一个带有赋值运算符的
类Foo
,如下所示:
class Foo {
Foo& operator=(Foo o) noexcept {
member = move(o.member);
return *this;
}
};
struct wrap { Foo m_ };
并将Foo
对象包装在struct
中,比如说struct wrap
,如下例所示:
class Foo {
Foo& operator=(Foo o) noexcept {
member = move(o.member);
return *this;
}
};
struct wrap { Foo m_ };
然后,wrap
将不会获得默认移动分配。对于wrap
要获得默认的noexcept
move分配,所有成员都必须具有noexcept
move分配-此确定通过签名进行。这就是标准,对于wrap
要获得默认的noexcept
移动分配,所有成员都必须具有签名为T&operator=(T&&)noexcept
的移动分配
修复方法是重新表述需求,使其表明,如果所有成员都满足is nothrow\u move\u assignable
,则结构或类将获得默认的noexcept
移动分配,而上述操作就是如此。也就是说,我们希望根据概念或操作语义来定义需求,而不是根据匹配精确签名来定义需求