代码之家  ›  专栏  ›  技术社区  ›  Tomilov Anatoliy

三元运算符中的条件移动或复制赋值

  •  0
  • Tomilov Anatoliy  · 技术社区  · 6 年前

    #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
    

    在标准赋值过程中,为避免使用标准赋值运算符的复制/赋值而在三值赋值的右边移动( b c )直接到左手边( a )视情况而定?

    2 回复  |  直到 6 年前
        1
  •  1
  •   Richard Hodges    6 年前

    有没有可能。。。编译器在使用三元运算符进行复制/移动赋值时避免使用临时值

    一般的 ,是的。允许编译器重新排列或省略代码 前提是 可观察结果 . 这被称为好像规则。

    编译器还可以在其他情况下省略副本,即使观察到的行为会发生变化,例如RVO(返回值优化)。

        2
  •  1
  •   Shafik Yaghmour    6 年前

    [class.copy.elision] ,其中包括哪些情况下,即使复制/移动有副作用,也可以排除。我们没有看到你的例子:

    当满足某些条件时,允许实现省略类的复制/移动构造 对象,即使为复制/移动操作和/或对象的析构函数选择了构造函数 有副作用。在这种情况下,实现将处理省略的复制/移动的源和目标 构造函数是对对象类型的rvalue引用,当目标 会被摧毁;否则,破坏发生在两个物体的时间较晚的时候 在下列情况下允许省略(可合并以消除多个副本):

    • 在具有类返回类型的函数的return语句中,当表达式的名称为 与函数具有相同类型(忽略cv限定)的处理程序(13.3))的异常声明 返回类型,通过直接构造自动对象可以省略复制/移动操作
    • 在抛出表达式(7.6.17)中,当操作数是非易失性自动对象的名称时 (函数或catch子句参数除外)其范围不超过 最里面的封闭try块(如果有),从操作数到 通过将自动对象直接构造到异常中,可以省略异常对象(13.1) 对象
    • 当异常处理程序的异常声明(第13条)声明相同的对象时 类型(cv限定除外)作为例外对象(13.1),可以通过以下方式省略复制操作 如果程序的意思是

    如果表达式在需要常量表达式的上下文中求值,则需要复制省略(7.7) 在恒定初始化(6.8.3.2)中。[注意:如果相同的表达式是 在另一个上下文中评估。尾注]

    推荐文章