Clang vs G++ 左值到右值的转换
Clang vs G++ lvalue to rvalue conversion
问题 与此 相关 。通过跟踪 slt_pair. h
和 move. h
,似乎 Clang 和 G++ 之间的区别是内部的。我试图模拟对象(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 如何处理 lvalue
到 rvalue
的转换,以及这些不同输出的真正原因。
非常感谢任何意见,谢谢。
更新: 我在接受的评论区得到了满意的答案。
我认为并非您示例中的所有内容都如您所想。 return 中的 static_cast
没有意义,cast1
和 cast2
的结果将自动成为右值,因为你 return 按值。此外,cast1
和 cast2
在内部也是相同的,因为 std::remove_reference_t<Foo>
只是 Foo
。如果您正在进行一些模板化,您将需要 remove_reference
。
此外,您将赋值与构造混合在一起。在 T1 = cast2(Foo());
中会发生以下情况:
Foo()
构造了一个未命名的临时文件。这输出 default
- 这个临时文件被复制到
cast2
的 foo
参数。这会输出 const
,因为我们试图从一个临时对象构造一个 Foo
对象,并且只有 const Foo&
,而不是 Foo&
可以绑定到一个临时对象。
static_cast
几乎什么都不做。
foo
是 returned。通过 return 值优化,应该调用的构造函数没有被调用。
- 我们使用默认(和隐式)赋值运算符
T1.operator=(const Foo&)
分配 returned 值。没有打印出来。
在 Foo const foo = T1
中调用构造函数。由于 T1
是左值,您将调用构造函数 Foo(Foo&)
并打印 non-const
。
问题 与此 slt_pair. h
和 move. h
,似乎 Clang 和 G++ 之间的区别是内部的。我试图模拟对象(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 如何处理 lvalue
到 rvalue
的转换,以及这些不同输出的真正原因。
非常感谢任何意见,谢谢。
更新: 我在接受的评论区得到了满意的答案。
我认为并非您示例中的所有内容都如您所想。 return 中的 static_cast
没有意义,cast1
和 cast2
的结果将自动成为右值,因为你 return 按值。此外,cast1
和 cast2
在内部也是相同的,因为 std::remove_reference_t<Foo>
只是 Foo
。如果您正在进行一些模板化,您将需要 remove_reference
。
此外,您将赋值与构造混合在一起。在 T1 = cast2(Foo());
中会发生以下情况:
Foo()
构造了一个未命名的临时文件。这输出default
- 这个临时文件被复制到
cast2
的foo
参数。这会输出const
,因为我们试图从一个临时对象构造一个Foo
对象,并且只有const Foo&
,而不是Foo&
可以绑定到一个临时对象。 static_cast
几乎什么都不做。foo
是 returned。通过 return 值优化,应该调用的构造函数没有被调用。- 我们使用默认(和隐式)赋值运算符
T1.operator=(const Foo&)
分配 returned 值。没有打印出来。
在 Foo const foo = T1
中调用构造函数。由于 T1
是左值,您将调用构造函数 Foo(Foo&)
并打印 non-const
。