我一直在编写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 ++编译器会“获取”这个,还是构建一个临时对象然后复制它?
答案 0 :(得分:1)
是的,一个好的编译器将消除这种情况下的额外开销。
我说"在这种情况下"因为它在很大程度上取决于构造函数(以及赋值运算符 - 它所说的"下面的构造函数/构造,读作"或赋值运算符")。如果构造函数影响(或"可能影响")全局状态,则编译器无法删除构造。影响全局状态将是读取或写入文件,更新全局变量,几乎任何对编译器都不知道" (没有源代码)将导致构造函数/副本消除到"失败"。
当然,如果没有消除构造函数/副本,使用setter的代码可能会更有效。在真实场景中,确切的度量只能通过基准测试来确定,因为在编译优化时,通常很难准确判断一行或多行代码实际上有什么影响 - 有时看起来很简单的东西相当复杂的东西(虽然不那么频繁=最终没有花费太多时间。