在 2012 年 C++now 大会的主题演讲中,Sean Parent 介绍了“汇参数”的概念。他的建议是,如果参数被函数“消耗”,则按值传递参数。然后根据其 R 值或 L 值 move 或复制接收器参数。
他明确提到赋值运算符作为具有接收参数的操作实例。
因此他在演讲中以这个实现为例:
object_t& operator = (object_t x)
{ object_ = move(x.object_); return *this; }
在以后的谈话中,例如在 Going Native 2013 上,他重复了指南,但提到由于语言缺陷,需要实现单独的 move 赋值运算符:
这是他幻灯片中的引文:
- 按值传递接收器参数并 move 或交换到位。
- 接收器参数是函数消耗或传递的任何参数。
- 赋值的参数是接收器参数。
- 但是,由于语言缺陷,您必须编写 move 赋值运算符。
我搜索了有关此特定语言缺陷的信息,但没有找到任何信息。
- 谁能解释一下这种语言缺陷是什么,以及为什么使用接收器参数的赋值运算符不起作用。
- 这种语言缺陷会在 C++14 中持续存在吗?
提前致谢, 约阿希姆
最佳答案
Sean Parents 在他的评论中回答了这个问题 link .
假设您有一个 class Foo
使用赋值运算符,如下例所示:
class Foo {
Foo& operator=(Foo o) noexcept {
member = move(o.member);
return *this;
}
};
然后包装一个Foo
struct
中的对象,说 struct wrap
就像下面的例子:
struct wrap { Foo m_ };
然后wrap
不会得到默认的 move 分配。对于 wrap
获得默认 noexcept
move 分配,所有成员必须有一个 noexcept
move 分配——这个决定是通过签名做出的。那是标准说的 wrap
获得默认 noexcept
move 任务所有成员必须有签名为T& operator=(T&&) noexcept
的 move 任务.
解决方法是重新表述要求,使其表示结构或类将获得默认值 noexcept
如果所有成员都满足 is_nothrow_move_assignable<T>
,则 move 分配- 以上就是这样做的。也就是说,我们希望根据概念或操作语义来定义需求,而不是根据匹配精确签名来定义需求。
关于c++11 - 赋值运算符的汇参数实现及语言缺陷,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25444201/