2017-07-12 45 views
0

假定代码位于内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); 
    } 
} 
+1

可能的重复:https://stackoverflow.com/questions/26949569/do-temp-variables-slow-down-my-program – Rakete1111

+1

你可以看看[编译器输出](https://godbolt.org/ )。如果您看到两者之间有任何差异,我会感到惊讶 – user463035818

+0

是的,我早些时候做过。汇编代码的某些部分在不同的地方,并且作为不熟悉这种语言的人我不确定这两种方式在结果中是否总是相同。 – trivelt

回答

1

在您简单的情况下,它不会有所作为,因为(主)函数创建和使用a之后结束。

如果一些代码更多行会跟随,所述a对象的破坏会发生在if块的main结束,而在一条线的情况下它在该单线的端部变得破坏。然而,这将是糟糕的设计,如果一个更复杂class A析构函数将使上的差异。

由于编译器优化性能问题应该总是通过使用Profiler测试具体代码来回答。

+0

谢谢!与我开发的应用程序中的真实代码相比,我的例子非常简化,但我的问题更广泛。为什么在''''''a'''的末尾可以完成对''''a'''的破坏,而不是'''if'''块的末尾? – trivelt

+0

@trivelt:你说的没错它的''if''块结束时是准确的。我将编辑我的答案以纠正此问题。 – bjhend

2

here。即使禁用了优化,两个版本的代码也没有区别。

使用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() 

所以他们几乎是相同的。当你意识到这两个版本之间的唯一区别是,在第一个我们指定的名称,我们的对象,而在第二,我们有不愿透露姓名的工作之一

这个结果是可以理解的。除此之外,它们都是在堆上创建的并以相同的方式使用。由于变量名对编译器没有任何意义 - 它只与代码读取器相关 - 它将两者视为相同。

相关问题