我应该只在免费商店上为一次调用创建对象吗?

Should I create object on a free store only for one call?

本文关键字:一次 调用 创建对象 免费 我应该      更新时间:2023-10-16

假设代码位于块if,那么在免费存储中创建对象和只对其执行一次调用有什么区别:

auto a = aFactory.createA();
int result = a->foo(5);

并直接在返回的指针上调用?

int result = aFactory.createA()->foo(5);

性能有什么不同吗?哪种方式更好?

#include <iostream>
#include <memory>
class A 
{
public:
int foo(int a){return a+3;}
};
class AFactory
{
public:    
std::unique_ptr<A> createA(){return std::make_unique<A>();}
};
int main()
{
AFactory aFactory;
bool condition = true;
if(condition)
{
auto a = aFactory.createA();
int result = a->foo(5);   
}
}

看这里。即使禁用了优化,为两个版本生成的代码也没有区别。

将 gcc7.1 与-std=c++1z -O0一起使用

auto a = aFactory.createA();
int result = a->foo(5);  

编译为:

lea     rax, [rbp-24]
lea     rdx, [rbp-9]
mov     rsi, rdx
mov     rdi, rax
call    AFactory::createA()
lea     rax, [rbp-24]
mov     rdi, rax
call    std::unique_ptr<A, std::default_delete<A> >::operator->() const
mov     esi, 5
mov     rdi, rax
call    A::foo(int)
mov     DWORD PTR [rbp-8], eax
lea     rax, [rbp-24]
mov     rdi, rax
call    std::unique_ptr<A, std::default_delete<A> >::~unique_ptr()

int result = aFactory.createA()->foo(5);

lea     rax, [rbp-16]
lea     rdx, [rbp-17]
mov     rsi, rdx
mov     rdi, rax
call    AFactory::createA()
lea     rax, [rbp-16]
mov     rdi, rax
call    std::unique_ptr<A, std::default_delete<A> >::operator->() const
mov     esi, 5
mov     rdi, rax
call    A::foo(int)
mov     DWORD PTR [rbp-8], eax
lea     rax, [rbp-16]
mov     rdi, rax
call    std::unique_ptr<A, std::default_delete<A> >::~unique_ptr()

所以它们几乎是相同的。

当您意识到两个版本之间的唯一区别是,在第一个版本中,我们将名称分配给我们的对象,而在第二个版本中,我们使用未命名的版本时,这种结果是可以理解的。除此之外,它们都是在堆上创建的,并以相同的方式使用。由于变量名对编译器没有任何意义 - 它只与代码阅读器相关 - 它将两者视为相同。

在您的简单情况下,它不会有什么区别,因为(main(函数在创建和使用a后立即结束。

如果接下来再多几行代码,则a对象的销毁将发生在mainif块的末尾,而在一行的情况下,它将在该单行的末尾被销毁。但是,如果更复杂的class A的析构函数会对此产生影响,那将是糟糕的设计。

由于编译器优化,性能问题应始终通过在具体代码上使用探查器进行测试来回答。