1

以下代码在 GCC 和 vc9 上编译时给出了不同数量的析构函数。AFAIK 在 vc9 上运行时显示 5 个析构函数,我理解。调用 + 重载运算符,并创建两个对象,返回时创建一个临时对象。这使得销毁 3 个对象成为可能。当调用重载 = 运算符时,会创建一个对象,并在返回时再次创建一个临时对象。这总共有五个破坏,不包括在 main 开始时创建的三个对象。

但是当我在 GCC 上编译时,我得到 3。

这让我猜测函数终止并返回时没有创建临时对象?或关于编译器之间不同行为的问题。我只是不知道,一些澄清会很好。

#include <iostream>
using namespace std;

class planetCord {
    double x, y, z;
public:
    planetCord() { x = y = z = 0; }
    planetCord(double j, double i, double k) { x = j; y = i; z = k; }    
    ~planetCord() { cout << "destructing\n"; }
    planetCord operator+(planetCord obj);
    planetCord operator=(planetCord obj);
    void show();
};

planetCord planetCord::operator +(planetCord obj) {
    planetCord temp;
    temp.x = x + obj.x;
    temp.y = y + obj.y;
    temp.z = z + obj.z;
    return temp;
}

planetCord planetCord::operator =(planetCord obj) {
    x = obj.x;
    y = obj.y;
    z = obj.z;
    return *this;
}

void planetCord::show() {
    cout << "x cordinates: " << x << "\n";
    cout << "y cordinates: " << y << "\n";
    cout << "z cordinates: " << z << "\n\n";
}

int main() {
    planetCord jupiter(10, 20, 30);
    planetCord saturn(50, 100, 200);
    planetCord somewhereDark;

    jupiter.show();
    saturn.show();
    somewhereDark.show();
    somewhereDark = jupiter + saturn;  
    jupiter.show();
    saturn.show();
    somewhereDark.show();
    return 0;
}
4

4 回答 4

3

GCC 正在实施“返回值优化”以跳过临时对象。将 VC9 设置为发布模式,它可能会这样做。

如果 GCC 真的很好,它会看到tempinsideoperator+将被默认初始化,就像,并且如果它试图内联函数,则somewhereDark可以直接使用引用。somewhereDark或者它看到按值传递是无用的,而是可以按引用传递。

于 2009-08-23T18:11:41.973 回答
2

C++ 编译器的一个允许但不是强制的优化是转紧序列:

ctor for new temporary object X
copy ctor from X to other object Y
dtor for X

直接在 Y 上执行 ctor。一个非常好的 C++ 优化器可以跨函数 clal 执行此操作(即,当 X 是函数的返回值时)。看起来 gcc 优化得更好。当您使用两个编译器的优化选项时,结果是否会发生变化?

于 2009-08-23T18:11:21.583 回答
2

您的代码有很多问题。我可以建议您研究两个概念 - 常量和引用。如果您的 C++ 教科书没有涵盖这些内容,请获取一本新教科书 - 我强烈推荐Koenig & Moo 的Accelerated C++

于 2009-08-23T18:23:04.103 回答
0

实际上,在 GCC 中,正在制作临时文件。他们是:

  • 在运算符+。
  • 由运算符+返回。
  • 由运算符= 返回。

在 MSVC 中(我认为;无法测试),也正在制作临时文件。然而,有些并没有像 GCC 那样被优化掉。他们是:

  • 作为 operator+ 的参数。
  • 在运算符+。
  • 由运算符+返回。
  • 作为 operator= 的参数。
  • 由运算符= 返回。

具有讽刺意味的是,我认为 MSVC 就在这里,因为我不确定 GCC 的行为是否是标准的。

要使它们的行为相同,请使用const引用而不是按值传递对象。

于 2009-08-23T18:17:49.107 回答