简体   繁体   中英

Passing pointers by value or by const ref?

In a nutshell, is it better to pass a pointer by value or by const reference?

I wrote a simple function to explore:

void foo(int* v) { std::cout << *v << endl; }

versus

void foo(int* const& v) { std::cout << *v << endl; }

I tried to look at the assembly generated but I'm not particularly good at assembly so I'm not sure I understand the difference. But there is a difference. In the first case, we get:

pushq   %rbp
pushq   %rbx
subq    $8, %rsp
movl    (%rdi), %esi
movl    std::cout, %edi
call    std::basic_ostream<char, std::char_traits<char> >::operator<<(int)

In the const& case, we get one more operation:

pushq   %rbp
pushq   %rbx
subq    $8, %rsp
movq    (%rdi), %rax
movl    std::cout, %edi
movl    (%rax), %esi
call    std::basic_ostream<char, std::char_traits<char> >::operator<<(int)

What does that difference mean (three mov 's instead of two) and what is the implication of that? (Basically, I have a struct Foo<T> where T could be a raw pointer or not, and am wondering if my function bar(const T&) should instead be bar(typename boost::call_traits<T>::type) . ).

Pass pointers by value, unless you need reference semantics.

Passing by reference is almost certainly implemented by passing a pointer. You'd pass the same amount of data as the pointer itself, but introduce an extra level of indirection, so it's likely to be less efficient than passing by value.

Having said that, the difference is likely to be tiny; so for generic code it's simpler to pass by const reference, unless you really need to micro-optimise at the level of single instructions. If you do then, as you say, boost::call_traits can help.

Passing pointers by reference will do the following:

Address: 0x00  -  42   (int)
Address: 0x11  -  0x00 (int*)
Address: 0x22  -  0x11 (int* const&)

This is basically what the compiler will generate for int* const&. Implementation wise, it will likely end up being int**.

So passing pointers by value will end up being more efficient, as you will copy the address of the int directly, without overhead of the third row.

For pointers, pass by value. By definition, passing a pointer to a pointer (which is what will be happening under the hood) can't be more efficient than passing a pointer. The extra line in the assembler (which I know very little about) suggests it is actually less efficient for you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM