0

Assuming that code is located inside if block, what are differences between creating object in a free store and doing only one call on it:

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

and making call directly on returned pointer?

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

Is there any difference in performance? Which way is better?

#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);   
    }
}
trivelt
  • 1,913
  • 3
  • 22
  • 44
  • 1
    Possible duplicate: https://stackoverflow.com/questions/26949569/do-temp-variables-slow-down-my-program – Rakete1111 Jul 12 '17 at 08:24
  • 1
    You can look at the [compiler output](https://godbolt.org/). I would be surprised if you see any difference between the two – 463035818_is_not_an_ai Jul 12 '17 at 08:28
  • Yes, I did it earlier. Some parts of assembly code are in different places and as a person who is not familiar which this language I'm not sure if both ways are always identical in their results. – trivelt Jul 12 '17 at 08:30

2 Answers2

2

Look here. There is no difference in code generated for both versions even with optimisations disabled.

Using gcc7.1 with -std=c++1z -O0

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

is compiled to:

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

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

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

So they are pretty much identical.

This outcome is understandable when you realise the only difference between the two versions is that in the first one we assign the name to our object, while in the second we work with an unnamed one. Other then that, they are both created on heap and used the same way. And since variable name means nothing to the compiler - it is only relevant for code-readers - it treats the two as if they were identical.

K. Kirsz
  • 1,384
  • 10
  • 11
1

In your simple case it will not make a difference, because the (main) function ends right after creating and using a.

If some more lines of code would follow, the destruction of the a object would happen at the end of the if block in main, while in the one line case it becomes destructed at the end of that single line. However, it would be bad design if the destructor of a more sophisticated class A would make a difference on that.

Due to compiler optimizations performance questions should always be answered by testing with a profiler on the concrete code.

bjhend
  • 1,538
  • 11
  • 25
  • Thanks! My example was very simplified compared to the real code in app which I develop, but my question was broader. Why destruction of the ```a``` could be done at the end of main rather than at the end of ```if``` block? – trivelt Jul 12 '17 at 09:41
  • @trivelt: You're right it's the end of the ``if`` block to be exact. I will edit my answer to correct this. – bjhend Jul 12 '17 at 11:40