gpt4 book ai didi

c++ - 函数返回的局部变量是否在 C++20 中自动移动?

转载 作者:行者123 更新时间:2023-12-04 11:47:03 25 4
gpt4 key购买 nike

请考虑一个 C++ 程序,其中函数 foo建立它的回归U来自 int 类型的局部变量的对象使用两个构造函数之一:

struct U {
U(int) {}
U(int&&) {}
};

U foo(int a = 0) { return a; }

int main() { foo(); }
在 C++17 模式下,程序被所有编译器接受,演示: https://gcc.godbolt.org/z/b8hhEh948
但是在 C++20 模式下,GCC 拒绝它并显示错误:
In function 'U foo(int)':
<source>:6:27: error: conversion from 'int' to 'U' is ambiguous
6 | U foo(int a = 0) { return a; }
| ^
<source>:3:5: note: candidate: 'U::U(int&&)'
3 | U(int&&) {}
| ^
<source>:2:5: note: candidate: 'U::U(int)'
2 | U(int) {}
| ^
演示: https://gcc.godbolt.org/z/fMvEPMGhq
我认为这是因为 C++20 特性 P1825R0: Merged wording for P0527R1 and P1155R3 (more implicit moves)
和函数 foo根据这个特征必须等价于
U foo(int a = 0) { return std::move(a); }
由于所有编译器的构造函数选择歧义而被拒绝,演示: https://gcc.godbolt.org/z/TjWeP965q
GCC 是 C++20 模式下上述示例中唯一正确的编译器吗?

最佳答案

这里发生的是 gcc 实现 P1825 的方式。
在这个例子中:

U foo(int a) {
return a;
}
C++17 和 C++20 语言规则(这里没有变化)是我们首先处理的 a作为右值,如果重载解析失败(在 C++17 中,还需要绑定(bind)到 int&&),那么我们处理 a作为左值。使用该规则,此代码有效 - a 的重载解析因为 xvalue 由于歧义而失败(因为 U 是一个愚蠢的类型),所以我们回退到处理 a作为左值,这成功了。
但是 gcc 的实现并没有这样做。相反,它处理 a作为也可以绑定(bind)到非常量左值引用的 xvalue,并执行单轮重载决议(这样做是为了避免破坏某些代码,请参阅 here )。单轮重载决议是模棱两可的,因为简单地处理 a因为 xvalue 是不明确的,并且这里没有相关的左值 ref 构造函数,所以 gcc 拒绝了这个例子。
但在这种情况下,我会说这是 U的错而不是 gcc 的错。如 U (a) 有两个构造函数接受 int const&int&&像往常一样或 (b) 有一个接受 int 的构造函数,该示例可以正常编译。请注意,在 (b) 情况下,C++17 规则将执行复制,但 C++20 规则将执行移动(因为我们不再要求构造函数专门采用右值引用)。

关于c++ - 函数返回的局部变量是否在 C++20 中自动移动?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68747489/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com