以父对象作为参数调用子对象的函数:复制两次的原因是什么?

发布于 2025-01-03 18:28:21 字数 1233 浏览 0 评论 0原文

具有以下代码:

#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


问题如下:

  1. 为什么我们在第一种情况下有双重复制?
  2. 为什么在第二种情况下我们只有一份副本?
  3. 第一种情况:为什么编译器不优化第一种情况(通过减少复制操作数量)?
  4. 执行以下代码:

    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:

  1. Why we have double copying in the first case?
  2. Why we have only one copying in the second case?
  3. The 1st case: why does compiler not optimizes the 1st case (by reducing copy operations quantity)?
  4. Does the following code:

    void f(int);
    //...
    double d;
    f(d);
    

also make double-copying?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

山人契 2025-01-10 18:28:21

这两种情况在 gcc 4.3.4 上的输出为:

----------
~A(2)
----------
~B
~A(3)

示例 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:

----------
~A(2)
----------
~B
~A(3)

Example 1
Example 2

This output can be explained as:
When you call f(b); an copy of the object of type B 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 type A 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 the main(), Since it is of the type of B destructors for base class A and derived class B 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文