以父对象作为参数调用子对象的函数:复制两次的原因是什么?
具有以下代码:
#include <iostream>
struct A
{
int x;
A(){}
~A(){std::cout <<"~A("<<x<<")\n";}
};
struct B: public A
{
};
void f(A a)
{
a.x = 2;
}
void main()
{
B b;
std::cout <<"----------\n";
b.x = 1;
f(b);
b.x = 3;
std::cout <<"----------\n";
}
在这种情况下,输出如下:
----------
~A(2)
~A(1)
----------
~A(3)
相同的代码,但虚拟函数被添加到父类:
#include <iostream>
struct A
{
int x;
A(){}
~A(){std::cout <<"~A("<<x<<")\n";}
virtual void ff() {}
A(A& ca): x(ca.x){}
};
struct B: public A
{
};
void f(A a)
{
a.x = 2;
}
void main()
{
B b;
std::cout <<"----------\n";
b.x = 1;
f(b);
b.x = 3;
std::cout <<"----------\n";
}
在这种情况下,我们有以下输出:
----------
~A(2)
----------
~A(3)
编辑:
编译器是:MSVCPP 10
问题如下:
- 为什么我们在第一种情况下有双重复制?
- 为什么在第二种情况下我们只有一份副本?
- 第一种情况:为什么编译器不优化第一种情况(通过减少复制操作数量)?
执行以下代码:
void f(int); //... 双 d; f(d);
也进行双重复制?
Having the following code:
#include <iostream>
struct A
{
int x;
A(){}
~A(){std::cout <<"~A("<<x<<")\n";}
};
struct B: public A
{
};
void f(A a)
{
a.x = 2;
}
void main()
{
B b;
std::cout <<"----------\n";
b.x = 1;
f(b);
b.x = 3;
std::cout <<"----------\n";
}
In this case the output is following:
----------
~A(2)
~A(1)
----------
~A(3)
The same code but virtual function is added to parent class:
#include <iostream>
struct A
{
int x;
A(){}
~A(){std::cout <<"~A("<<x<<")\n";}
virtual void ff() {}
A(A& ca): x(ca.x){}
};
struct B: public A
{
};
void f(A a)
{
a.x = 2;
}
void main()
{
B b;
std::cout <<"----------\n";
b.x = 1;
f(b);
b.x = 3;
std::cout <<"----------\n";
}
In this case we have the following output:
----------
~A(2)
----------
~A(3)
EDIT:
Compiler is: MSVCPP 10
The questions are the following:
- Why we have double copying in the first case?
- Why we have only one copying in the second case?
- The 1st case: why does compiler not optimizes the 1st case (by reducing copy operations quantity)?
Does the following code:
void f(int); //... double d; f(d);
also make double-copying?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这两种情况在 gcc 4.3.4 上的输出为:
示例 1
示例 2
此输出可以解释为:
当您调用
f(b);
时,会创建B
类型的对象的副本,因为它是按值传递的。但是存在对象切片,因为函数参数采用
A
类型的对象。因此,函数中的对象现在属于A
类型,并且在从函数返回时被销毁,导致调用输出~A(2)
。以下两条痕迹来自
main()
中创建的对象b
的销毁,因为它的类型是B
基类A
和派生类B
的析构函数都被调用。我不确定我是否错过了 gcc 在这种情况下可能执行的任何明显优化,但对我来说,输出看起来几乎符合预期。
The output on gcc 4.3.4 for both cases is:
Example 1
Example 2
This output can be explained as:
When you call
f(b);
an copy of the object of typeB
is created since it is pass by value.But there is Object slicing, since the function parameter takes on object of type
A
. Thus the object in the function now is of the typeA
and it gets destroyed while returning from the function resulting in call output~A(2)
.The following two traces are from the destruction of the object
b
which is created in themain()
, Since it is of the type ofB
destructors for base classA
and derived classB
both are called for it.I am not sure if I missed out any obvious optimization that gcc might be performing in this case but for me the outputs look pretty much as expected.