Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/apache-flex/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 复制分配运算符中的按值传递与按引用传递_C++_Copy Assignment_Copy And Swap - Fatal编程技术网

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()
then
function()
仍然返回一个右值,
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;
}