0

我已经编写 C++ 很长时间了,所以我不知道这一点感到很傻,但是......

我经常编写对性能敏感的代码,当我这样做时,我会尽量避免堆分配。为此,我经常重复使用预先分配的小对象数组,而不是为每个单独的对象调用 new 和 delete。

在这种情况下,我通常会这样做:

class MyClass
{
private:
    int x, y;

public:
    inline void Set(_x, _y) { x = _x; y = _y; }
};

...

MyClass &objectToReuse = someArray[someIndex];

objectToReuse.Set(someXValue, someYValue);

但是我怀疑这个更好看的版本会生成相同的代码:

class MyClass
{
private:
    int x, y;

public:
    inline MyClass(_x, _y) : x(_x), y(_y) {}
};

...

MyClass &objectToReuse = someArray[someIndex];

objectToReuse = MyClass(someXValue, someYValue);

现代 C++ 编译器会“得到”这个,还是会构造一个临时对象然后复制它?

4

1 回答 1

1

是的,一个好的编译器会消除这种情况下的额外开销。

我说“在这种情况下”是因为它在很大程度上取决于构造函数中发生的事情(以及赋值运算符 - 它在下面说“构造函数/构造,读作“或赋值运算符”)。如果构造函数影响(或“可能影响”)全局状态,则编译器无法删除该构造。影响全局状态将是读取或写入文件,更新全局变量,几乎所有对编译器不“知道”(不知道)的函数的调用'没有源代码)将导致构造函数/复制消除“失败”。

自然,如果没有消除构造函数/副本,则使用 setter 的代码可能会更有效。在实际场景中,确切的衡量标准只能通过基准测试来确定,因为通常很难准确判断在优化编译时一行或多行代码实际产生的影响 - 看起来非常简单的东西有时会产生相当大的影响,看起来很复杂的东西可以(虽然不太常见=最终根本不需要太多时间。

于 2013-07-24T11:18:23.867 回答