Clang vs G++ 左值到右值的转换

Clang vs G++ lvalue to rvalue conversion

问题 与此 相关。通过跟踪 slt_pair. hmove. h,似乎 ClangG++ 之间的区别是内部的。我试图模拟对象(pair.first)的赋值与std_pair.h的实现相同,输出与Clang输出相同,这是合理的输出,但是为什么当使用成对时它会发生变化。

#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

}

Clang 如何处理 lvaluervalue 的转换,以及这些不同输出的真正原因。


非常感谢任何意见,谢谢。

更新: 我在接受的评论区得到了满意的答案。

我认为并非您示例中的所有内容都如您所想。 return 中的 static_cast 没有意义,cast1cast2 的结果将自动成为右值,因为你 return 按值。此外,cast1cast2 在内部也是相同的,因为 std::remove_reference_t<Foo> 只是 Foo。如果您正在进行一些模板化,您将需要 remove_reference

此外,您将赋值与构造混合在一起。在 T1 = cast2(Foo()); 中会发生以下情况:

  1. Foo() 构造了一个未命名的临时文件。这输出 default
  2. 这个临时文件被复制到 cast2foo 参数。这会输出 const,因为我们试图从一个临时对象构造一个 Foo 对象,并且只有 const Foo&,而不是 Foo& 可以绑定到一个临时对象。
  3. static_cast 几乎什么都不做。
  4. foo 是 returned。通过 return 值优化,应该调用的构造函数没有被调用。
  5. 我们使用默认(和隐式)赋值运算符 T1.operator=(const Foo&) 分配 returned 值。没有打印出来。

Foo const foo = T1 中调用构造函数。由于 T1 是左值,您将调用构造函数 Foo(Foo&) 并打印 non-const