我一直在研究有关NRVO的this文章。
class RVO
{
public:
RVO(){
printf("I am in constructor\n"); }
RVO(const RVO& c_RVO) {
printf("I am in copy constructor\n"); }
~RVO(){
printf("I am in destructor\n"); }
int mem_var;
};
RVO MyMethod(int i)
{
RVO rvo;
rvo.mem_var = i;
return (rvo);
}
int main()
{
RVO rvo;
rvo=MyMethod(5);
}
视觉工作室的输出如下,这就是我理解的方式
I am in constructor // main rvo construction
I am in constructor //MyMethod rvo construction
I am in copy constructor //temporary created inside MyMethod
I am in destructor //Destroying rvo in MyMethod
I am in destructor //Destroying temporary in MyMethod
I am in destructor //Destroying rvo of main
如果我把主要写为
int main()
{
RVO rvo = MyMethod(5);
return 0;
}
输出如下以及如何理解
I am in constructor //MyMethod rvo construction
I am in copy constructor //temporary created inside MyMethod
I am in destructor //Destroying rvo in MyMethod
I am in destructor //Destroying rvo of main
为什么在第二个版本的Mymethod
中临时没有被销毁?
为什么复制构造函数没有在RVO rvo = MyMethod(5);
中调用。我认为复制构造函数应该在第二个版本中调用两次,一个用于临时在Mymethod
内创建,另一个用于RVO rvo = MyMethod(5);
我知道有些电话可能会被删除。有人可以帮忙解释这些电话。
编辑:
使用return rvo
代替return (rvo)
会将输出更改为
第一种情况
I am in constructor
I am in constructor
I am in destructor
I am in destructor
第二种情况
I am in constructor
I am in destructor
我想当我删除括号时,NRVO会启动。但是当没有优化时我对第一个输出更感兴趣
答案 0 :(得分:0)
第一个descructor调用是来自主要的rvo的解构。首先创建的对象必须删除。这不是复制作业,是复制构造。
答案 1 :(得分:0)
更新:使用return (rvo);
而不是I am in constructor
I am in constructor
I am in destructor
I am in destructor
来解决更新程序的输出
MyMethod::rvo
您看到这一点的原因是两个对象(main::rvo
和this
)都经过默认构造,然后后者被分配为单独的操作但您没有记录它。< / p>
通过输出对象的地址可以更好地了解发生的事情,并且可以调用#include <cstdio>
#include <iostream>
class RVO
{
public:
RVO(){
printf("%p constructor\n", this); }
RVO(const RVO& c_RVO) {
printf("%p copy constructor, rhs %p\n", this, &c_RVO); }
~RVO(){
printf("%p destructor\n", this); }
int mem_var;
};
RVO MyMethod(int i)
{
RVO rvo;
std::cout << "MyMethod::rvo @ " << &rvo << '\n';
rvo.mem_var = i;
return (rvo);
}
int main()
{
RVO rvo=MyMethod(5);
std::cout << "main::rvo @ " << &rvo << '\n';
}
指针值作为函数:
cl /O2
输出还取决于您是否使用optimisations进行编译;您链接到Microsoft文档,所以也许您正在使用Microsoft编译器 - 尝试main
。
为什么在第二个版本的Mymethod中暂时没有销毁?
没有临时性 - 002AFA4C constructor
MyMethod::rvo @ 002AFA4C // MyMethod::rvo's constructed
002AFA70 copy constructor, rhs 002AFA4C // above is copied to 2AFA70
002AFA4C destructor // MyMethod::rvo's destructed
main::rvo @ 002AFA70 // turns out the copy above was directly to main::rvo
002AFA70 destructor // main::rvo's destruction
中的对象是直接复制构造的。引导你完成它:
002FF890 constructor // we find out this is main::rvo below
002FF864 constructor // this one's MyMethod::rvo
MyMethod::rvo @ 002FF864
002FF888 copy constructor, rhs 002FF864 // 2FF888 is some temporary
002FF864 destructor // there goes MyMethod::rvo
002FF888 destructor // there goes the temporary
main::rvo @ 002FF890
002FF890 destructor // and finally main::rvo
[Alf下面的评论]&#34;直接复制构造&#34;对我来说并不完全有意义。我认为OP意味着rvo局部变量
考虑第一版程序的增强输出(无优化):
I am in constructor // main rvo construction
I am in constructor //MyMethod rvo construction
I am in copy constructor //temporary created inside MyMethod
I am in destructor //Destroying rvo in MyMethod
I am in destructor //Destroying temporary in MyMethod
I am in destructor //Destroying rvo of main
如果我们将其重新绑定到OP的输出和注释......
main::rvo
OP(正确)将复制构造的对象称为临时对象。当我说到程序的第二个版本时,#34;那里没有临时版本 - main中的对象是直接复制构造的。&#34; - 我的意思是,我们在上面直接分析的第一个程序中没有临时等价物,而是MyMethod::rvo
从<button type="button" class="btn btn-primary close" href="#">Dismiss</button>
复制的{{1}}。