对于下面的代码片段:
#include <utility>
#include <iostream>
#define C(name) (name ? name : "nullptr")
#define PP { std::cout << __PRETTY_FUNCTION__ << " : " << C(name) << '\n'; }
#define T { std::cout << __PRETTY_FUNCTION__ << " : " << C(name) << " -> " << C(rhs.name) << '\n'; }
struct A
{
const char * name = nullptr;
A(const char * name) : name{name} PP
A(A && rhs) : name{std::exchange(rhs.name, nullptr)} PP
A(const A & rhs) : name{rhs.name} PP
A & operator = (A && rhs) { T; std::swap(name, rhs.name); return *this; }
A & operator = (const A && rhs) { T; name = rhs.name; return *this; }
~A() PP
};
#include <random>
int main()
{
std::random_device d;
A a{"a"};
A b{"b"};
A c{"c"};
std::cout << "begin\n";
a = ((d() % 2) == 0) ? b : std::move(c);
std::cout << "end\n";
}
可能有以下两种输出:
A::A(const char*) : a
A::A(const char*) : b
A::A(const char*) : c
begin
A::A(A&&) : c
A& A::operator=(A&&) : a -> c
A::~A() : a
end
A::~A() : nullptr
A::~A() : b
A::~A() : c
和
A::A(const char*) : a
A::A(const char*) : b
A::A(const char*) : c
begin
A::A(const A&) : b
A& A::operator=(A&&) : a -> b
A::~A() : a
end
A::~A() : c
A::~A() : b
A::~A() : b
在上述情况下,编译器是否有可能(根据标准)避免在使用三元运算符进行复制/move 赋值期间使用临时值,并分派(dispatch)复制或 move 赋值运算符来分配右侧的值( b
或 c
) 根据条件直接到左侧 (a
)?
最佳答案
Is it possible ... for the compiler to avoid using of temporary value during copy/move assignment with ternary operator
由于您编写代码的方式,这是一个有趣的问题。
一般,是的。允许编译器重新排列或删除代码前提是可观察到的结果与它执行代码时的结果相同。这称为假设规则。
编译器还可以在其他情况下省略拷贝,即使观察到的行为会发生变化,例如RVO(返回值优化)。
但是在您的情况下,所有构造函数都具有无法更改的可观察行为 - 它们将字符发送到标准输出!
因此在这种特殊情况下,编译器别无选择,只能遵循原始代码的流程。
关于c++ - 三元运算符中的条件 move 或复制赋值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53019435/