I have the following code:
#include <boost/shared_ptr.hpp>
struct Foo { int a; };
static int A;
void
func_shared(const boost::shared_ptr<Foo> &foo) {
A = foo->a;
}
void
func_raw(Foo * const foo) {
A = foo->a;
}
I thought the compiler would create identical code, but for shared_ptr
version an extra seemingly redundant instruction is emitted.
Disassembly of section .text:
00000000 <func_raw(Foo*)>:
0: 55 push ebp
1: 89 e5 mov ebp,esp
3: 8b 45 08 mov eax,DWORD PTR [ebp+8]
6: 5d pop ebp
7: 8b 00 mov eax,DWORD PTR [eax]
9: a3 00 00 00 00 mov ds:0x0,eax
e: c3 ret
f: 90 nop
00000010 <func_shared(boost::shared_ptr<Foo> const&)>:
10: 55 push ebp
11: 89 e5 mov ebp,esp
13: 8b 45 08 mov eax,DWORD PTR [ebp+8]
16: 5d pop ebp
17: 8b 00 mov eax,DWORD PTR [eax]
19: 8b 00 mov eax,DWORD PTR [eax]
1b: a3 00 00 00 00 mov ds:0x0,eax
20: c3 ret
I'm just curious, is this necessary, or it is just an optimizer's shortcoming?
Compiling with g++ 4.1.2
, -O3 -NDEBUG
.
It's not a 'redundant' instruction.
The relevant section of the first code snippet is equivalent to: *p
Whilst in the second it's equivalent to: **p
Due to shared_ptr's internals there is a second level of indirection. This is not something the optimizer can 'fix'.
At any rate, the difference is negligible.
EDIT:
Whoops! My apologies, I misread your code.
You are passing the shared_ptr BY REFERENCE in your code. That will pass it "by pointer" at the ASM level.
So you're passing a pointer to a shared_ptr, and that shared_ptr contains a pointer to your object.
Hence the two levels of indirection.
Sorry for the confusion. :)