我很困惑与问候如何编译和链接处理的事实,在电话会议上要求ER功能的依靠,如果函数使用静脉阻塞或NRVO不同.
这可能是我的误解,但我的假设是通常没有RVO或NRVO
std::string s = get_string();
Run Code Online (Sandbox Code Playgroud)
如果get_string不执行N?RVO但是如果get_string执行N?RVO调用代码什么也不做,并且s由函数get_string构造到位,则涉及从get_string的结果移动构造s .
编辑:这是我如何设想get_string调用程序操作,如果没有N?RVO:
现在还有RVO
无论如何,调用者都为返回对象分配空间.从调用者的角度来看,函数是否使用RVO并不重要.
你也混淆了两个独立的复制品.有一个RVO,它将函数局部变量的副本省略到返回值,并且从函数返回值到被初始化的对象的另一个副本也经常被省略.
基本上,没有任何省略,你可以把OP的调用看作是这样的(忽略任何别名问题,这实际上都可以直接在汇编中实现):
void get_string(void* retval)
{
std::string ret;
// do stuff to ret
new(retval) std::string(std::move(ret));
}
char retval[sizeof(std::string)];
get_string(retval);
std::string s(std::move(*(string*)retval));
Run Code Online (Sandbox Code Playgroud)
字符串ret被复制(或移动,在这种情况下)两次:一次从ret所述retval缓冲器,并从一次retval到s.
现在,应用NRVO后,只会get_string改变定义:
void get_string(void* retval)
{
std::string& ret = *new(retval) std::string;
// do stuff to ret
}
Run Code Online (Sandbox Code Playgroud)
从来电者的角度来看,一切都没有改变.该函数只是直接初始化它将返回到调用者为返回值分配的空间的对象.现在字符串只移动一次:从.retval到s.
现在调用者也可以删除副本,因为不需要分配单独的返回值,然后将其复制到正在初始化的对象中:
char retval[sizeof(std::string)];
get_string(retval);
std::string& s(*(string*)retval);
Run Code Online (Sandbox Code Playgroud)
以这种方式,s直接初始化get_string,并且不执行复制或移动.
| 归档时间: |
|
| 查看次数: |
394 次 |
| 最近记录: |