这就是C 14标准所说的[12.8 / 32]
When the criteria for elision of a copy/move operation are met,but
not for an exception-declaration,and the object to be copied is
designated by an lvalue,or when the expression in a return statement
is a (possibly parenthesized) id-expression that names an object with
automatic storage duration declared in the body or
parameter-declaration-clause of the innermost enclosing function or
lambda-expression,overload resolution to select the constructor for
the copy is first performed as if the object were designated by an
rvalue. If the first overload resolution fails or was not performed,
or if the type of the first parameter of the selected constructor is
not an rvalue reference to the object’s type (possibly cv-qualified),
overload resolution is performed again,considering the object as an
lvalue. [ Note: This two-stage overload resolution must be performed
regardless of whether copy elision will occur. It determines the
constructor to be called if elision is not performed,and the selected
constructor must be accessible even if the call is elided. — end note
]
以下是Effective Modern C一书中的解释
The part of the Standard blessing the RVO goes on to say that if the
conditions for the RVO are met,but compilers choose not to perform
copy elision,the object being returned must be treated as an rvalue.
In effect,the Standard requires that when the RVO is permitted,
either copy elision takes place or std::move is implicitly applied to
local objects being returned
据我所知,当返回物体最初不能被省略时,它应被视为右值.在这些示例中,我们可以看到,当我们传递大于5的参数时,移动了对象,否则会被复制.当我们知道RVO不会发生时,这是否意味着我们应该明确地写std :: move?
#include <iostream> #include <string> struct Test { test() {} Test(const Test& other) { std::cout << "Test(const Test&)" << std::endl; } Test(Test&& other) { std::cout << "Test(const Test&&)" << std::endl; } }; Test foo(int param) { Test test1; Test test2; return param > 5 ? std::move(test1) : test2; } int main() { Test res = foo(2); }
该程序的输出是Test(const Test&).
解决方法
Test foo(int param) { Test test1; Test test2; if (param > 5) return std::move(test2); else return test1; }
将输出Test(Test&&).
如果你写(param> 5)会发生什么?std :: move(test1):test2是:
>三元运算符结果推导为prvalue [expr.cond]/5
>然后test2通过lvalue-to-rvalue转换,根据[expr.cond]/6的要求导致copy-initialization
>然后返回值的移动构造被省略[class.copy]/31.3
因此,在您的示例代码中,移动elision发生,然而在形成三元运算符的结果所需的复制初始化之后.
原文地址:https://www.jb51.cc/c/117959.html
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。