c++ - 尽管按名称返回,为什么仍复制局部变量?

标签 c++ c++11

在以下代码片段中,return s给出警告 local variable 's' will be copied despite being returned by name [-Wreturn-std-move] .为什么会这样?
我使用这个 lambda 函数的目标是获取输入字符串的所有权,然后在通过 RVO 或移动语义修改后返回它。我真的很想避免任何复制。

const auto to_upper = [](std::string&& s) {
    std::transform(s.begin(), s.end(), s.begin(), 
        [](unsigned char c){ return std::toupper(c); }
    );
    return s;
};
返回 std::move(s)std::forward<std::string>(s)将解决这个问题,但我认为这没有必要,因为编译器可以省略复制构造函数的使用。另外,我想我应该使用 std::forward但哪一个是正确的,为什么?

最佳答案

In the following code snippet, the return s gives the warning local variable 's' will be copied despite being returned by name [-Wreturn-std-move]. Why is this the case?


那是因为自动推导出函数或 lambda 捕获调用运算符的返回值类型永远不是引用。见 Return type deduction

If the return type does not use decltype(auto), the deduction follows the rules of template argument deduction.


Template argument deduction从不推导出引用。
如果需要引用返回值,则必须明确指定:
const auto to_upper = [](std::string&& s) -> std::string&& {
    // ...
    return std::move(s);
}
std::move(s)修复编译器警告,但它不会更改返回值类型,除非明确指定引用返回类型。 An example .编译器警告被破坏。

当函数按值返回时,函数参数免于返回值复制省略。
copy elision详细信息:

In a return statement, when the operand is the name of a non-volatile object with automatic storage duration, which isn't a function parameter or a catch clause parameter, and which is of the same class type (ignoring cv-qualification) as the function return type. This variant of copy elision is known as NRVO, "named return value optimization".


class.copy.elision :

in a return statement in a function with a class return type, when the expression is the name of a non-volatile object with automatic storage duration (other than a function parameter or a variable introduced by the exception-declaration of a handler ([except.handle])) with the same type (ignoring cv-qualification) as the function return type, the copy/move operation can be omitted by constructing the object directly into the function call's return object


函数参数和返回值必须同时存在。构造返回值时,局部变量仍然存在,并且可能引用函数参数。只有在构造返回值之后,才会执行局部变量的析构函数。那些析构函数可能会引用函数参数,这就是为什么它的存储不能用于先前构造的返回值的原因。

关于c++ - 尽管按名称返回,为什么仍复制局部变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66787397/

相关文章:

c++ - 无法使用 CImg 加载任何图像

c++ - 如何从二进制文件中写入/读取特征矩阵

c++11 默认初始化/值初始化/直接初始化

c++ - STL 容器的范围插入函数在 c++11 下返回 void?

c++ - 标准中哪里说不允许声明 `auto f()() ->int;`?

c++ - 使用模板时,如何解决以下编译器错误,以实现程序所需的行为?

c++ - 如果 C++ 中的一个变量为空,是否有一种速记方法来打印不同的变量?

c++ - 添加到 C++ 中的集合

c++ - 在 C++ 中使用 posix pipe() 和 dup() 来重定向 I/O 问题

c++ - 在 C++ 中初始化静态常量数组的特定元素