c++ - 三元运算符中的条件 move 或复制赋值

标签 c++ language-lawyer ternary-operator move-semantics value-categories

对于下面的代码片段:

#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 赋值运算符来分配右侧的值( bc) 根据条件直接到左侧 (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/

相关文章:

c++ - std::type_info::hash_code() 的唯一性和 "should"的含义

java - 通过蓝牙将超声波传感器的数据从 Arduino 发送到 Android

java - 是否存在不必要的分号语法错误?

rust - Rust的确切自动引用规则是什么?

javascript - 使用 ESLint `indent` 规则忽略模板文字中的缩进

javascript - AngularJS 三元表达式无效

opengl - GLSL 扩展支持 ? : ternary operator?

c++ - Gamma 校正看起来没有正确校正,这是线性的吗?

c++ - 在 boost::asio::serial_port 上解锁同步读取

c++ - unsigned int 是 `simple-type-specifier`