Clang vs G++ lvalue to rvalue conversion

旧城冷巷雨未停 提交于 2020-07-09 11:55:56

问题


The question related to this one. By tracing slt_pair. h and move. h, it's seems that the difference between Clang and G++ is internally. I have tried to simulate the assignment of the object (pair.first) as same as the implementation of std_pair.h, the output is same as Clang output it's reasonable output, but why when using pairs it's changes.

#include <iostream>

struct Foo {
  Foo() {
    std::cout << "default" << std::endl;
  }
  Foo(Foo& f2) {
    std::cout << "non-const" << std::endl;
  }
  Foo(const Foo& f2) {
    std::cout << "const" << std::endl;
  }
};

// static_cast Foo lvalue to rvalue
Foo cast1(Foo foo){

    return static_cast<Foo&&>(foo);
}

// same : check weather foo and Foo are the same type
Foo cast2(Foo foo){
     return static_cast<typename std::remove_reference<Foo>::type&&>(foo);
}

int main() {

        Foo T1; // pair Foo object

        std::cout<<"Start"<<std::endl;
        std::cout<<std::endl;
        

        // (&&) rvalue casting
        T1 = cast2(Foo()); // First pair object

        std::cout << std::endl;

        Foo const foo = T1;// Second pair object

}

How Clang deals with conversion lvalue to rvalue and what the real reason for these different outputs.


Any opinion is highly appreciated, Thanks.

Update: I have got a satisfying answers on the comments section of the accepted one.


回答1:


I think not everything in your example does what you think it does. The static_cast in the returns is meaningless, the result of cast1 and cast2 will automatically be an rvalue since you return by value. Further, cast1 and cast2 are also internally identical since std::remove_reference_t<Foo> is just Foo. You would need remove_reference if you had some templating going on.

Furthermore, you are mixing assignments with constructions. In T1 = cast2(Foo()); the following happens:

  1. A unnamed temporary is constructed by Foo(). This outputs default
  2. This temporary is copied to the foo argument of cast2. This outputs const, since we try to construct a Foo object from a temporary, and only const Foo&, not Foo&, can bind to a temporary.
  3. The static_cast does pretty much nothing.
  4. foo is returned. By return value optimization, the constructor that should be called, is not called.
  5. We assign the returned value by using the default (and implicit) assignment operator T1.operator=(const Foo&). Nothing gets printed.

In Foo const foo = T1 you call a constructor. Since T1 is an lvalue, you will call the constructor Foo(Foo&) and non-const is printed.



来源:https://stackoverflow.com/questions/62128493/clang-vs-g-lvalue-to-rvalue-conversion

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!