C++ 复制分配运算符中的按值传递与按引用传递
首先也是最重要的是,有一个类似的流行帖子。 被接受的答案有到的链接 接受页和链接页都声明复制分配运算符的常用实现是(从上一个链接复制和粘贴) 但那C++ 复制分配运算符中的按值传递与按引用传递,c++,copy-assignment,copy-and-swap,C++,Copy Assignment,Copy And Swap,首先也是最重要的是,有一个类似的流行帖子。 被接受的答案有到的链接 接受页和链接页都声明复制分配运算符的常用实现是(从上一个链接复制和粘贴) 但那 T& operator=(T x) // x is a copy of the source; hard work already done { swap(*this, x); // trade our resources for x's return *this; // our (old) resources
T& operator=(T x) // x is a copy of the source; hard work already done
{
swap(*this, x); // trade our resources for x's
return *this; // our (old) resources get destroyed with x
}
更好的方法是由编译器进行复制省略优化,或者通常,总是按值传递,而不是按引用传递,然后复制按引用传递的参数
我同意第二个选项与第一个选项相等或更好,但并不比第一个更糟,但我不明白为什么第一个选项在第一个地方竟然是这样写的。我不明白为什么需要临时变量和交换
相反,我们能不能做一些类似的事情:
T& T::operator=(T const& x) // x is a reference to the source
{
this->member_var = x.member_var;
//if we have to do a deep copy of something, implement that here
return *this;
}
它不使用复制构造函数。如果有多个成员,则赋值运算符不是异常安全的:
T& T::operator=(T const& x)
{
this->member_var1 = x.member_var1;
this->member_var2 = x.member_var2; // if an exception occurs here, this->member_var1 will still be changed
return *this;
}
@这完全取决于复制构造函数的实现方式。。。关于复制/交换的任何内容都不会强制进行浅层复制。关于我们使用复制/交换的原因及其成本,您是对的。复制/交换不是必需的,也不是自动的更好的解决方案。但是它非常有用。你可能从相关问题中错过了一个好处,那就是异常安全。使用复制/交换时,分配成功或
此
保持不变<代码>交换应始终为noexcept
,因此只有副本才能失败。如果是这样,则不会发生交换。执行此操作通常会有一点开销,与使用复制/交换的开销没有太大区别。当调用操作符=
时,如果传递的对象是右值,则会构造参数x
。例如,在foo=std::move(bar)
中的foo::operator=(foo x)
中,参数x
由bar
构造而成。然后将x
与*this
交换。但是在这种情况下,x
us从不使用右值,只有std::move(bar)
生成右值引用。x
与任何其他命名变量一样是左值表达式。它有一个名字(x
),你可以取它的地址(&x
)。它的构造方式不会改变它的值类别。诀窍在于,值类别应用于表达式,而不是它们包含或表示的值。如果你有tx
则x
为左值。如果你有T函数()代码>然后调用函数结果是一个右值。如果你做了x=function()
thenfunction()
仍然返回一个右值,x
仍然是一个左值,即使它们现在表示相同的状态。这与线程安全无关(没有同步,多成员交换就不会神奇地“安全”无论是哪一种,只要尝试在没有同步或原子的情况下读取数据,都可能读取垃圾,特别是在具有弱有序内存模型的系统上,或者由于撕裂),这都是关于强异常保证的。
T& T::operator=(T const& x)
{
this->member_var1 = x.member_var1;
this->member_var2 = x.member_var2; // if an exception occurs here, this->member_var1 will still be changed
return *this;
}