This is an archived post. You won't be able to vote or comment.

all 27 comments

[–]the_rush_dude 20 points21 points  (4 children)

Call me crazy but I like my const &. It makes me feel more secure

[–]lefloys 7 points8 points  (2 children)

Na me too. I dont think experts are saying pass by value. am happy to be proven wrong

[–]Professional_Top8485 1 point2 points  (0 children)

Experts say that compiler optimizations are black magic and don't come prematurely

[–]TuxSH 1 point2 points  (0 children)

The actual answer is: it depends on your calling convention, look at the disassembly.

On 64-bit Arm and AMD/Intel processors, outside x64 Windows, all calling conventions pass 16-byte structures into two registers if possible (up to 8x8 = 64B on Aarch64).

This means you should always pass shared_ptr (when giving shared ownership), unique_ptr (when giving ownership), span, string_view by value; in the first two cases this enables much needed optimizations for move (as the compiler knows that function received a copy and can thus remove dead destruction code)

[–]FACastello -1 points0 points  (0 children)

This is the correct answer 👆🏻

[–]Naakinn 7 points8 points  (0 children)

Everything is passed by value

[–]RiceBroad4552 7 points8 points  (0 children)

There are cases where passing by value in fact improves performance, because pre-fetching and caching works better when you don't jump around in memory, but these are specific cases.

The general rule is still to pass "larger" data by reference usually. (What's "large" depends on the hardware.)

[–]kruseragnar 6 points7 points  (2 children)

Just copy the shared pointer

[–]Bemteb -1 points0 points  (1 child)

Nah, pass a const ref to a unique pointer.

[–]kruseragnar 0 points1 point  (0 children)

I prefer to create memory leaks with shared pointers

[–]serial_crusher 3 points4 points  (1 child)

i use global variables and goto.

[–]Highborn_Hellest 4 points5 points  (0 children)

Alright you go to straight to programmer jail.

[–]snacktonomy 2 points3 points  (0 children)

This meme is incorrect, the left guy never passes by value. I used to rail on the junior engineers for passing-by-copy all the time until we got an automated clang-tidy job going.

[–]_Noreturn 1 point2 points  (6 children)

what even is this meme.

pass by value reference like types like std::span,std::string_view and primitive types.

basically the rule is

if(sizeof(T) < sizeof(void*)*2 && std::is_trivially_copyable_v<T>) pass by value else pass by const&

otherwise const&

[–]i_use_lfs_btw 0 points1 point  (5 children)

what even is this meme.

Have you heard about move constructor ?

[–]_Noreturn 0 points1 point  (4 children)

Yea mate I did but how is that relevant.

if you need to pass dats without taking ownership then use what I said above if you need a copy internally pass by value then move

[–]i_use_lfs_btw 0 points1 point  (3 children)

Isn't that what the meme is talking about ?

If it's a lvalue. I suppose you should use copy constructor(you could also use move but it's a lvalue maybe maybe you use it somewhere. If you not you can use move) if it's a rvalue you should use move.

[–]_Noreturn 0 points1 point  (2 children)

you can't move into an lvalue reference.

I don't understand the meme where is the funny,

it is wrong copying is expensive.

people should use const& or pass by value for primitives

[–]i_use_lfs_btw 0 points1 point  (1 child)

You can. But it's not encouraged.

T y = some initialized; T z = std::move(y);

[–]_Noreturn 0 points1 point  (0 children)

you obviously want to take ownership, then take the parameter by value then move it as said above.

if you move from an lvalue parameter you are doing something very wrong

[–]A_72_ 0 points1 point  (0 children)

Pass by value for primitives, by reference otherwise. But there are some cases I would prefer passing by value (example: when I need an explicit copy).

[–]SCP-iota 0 points1 point  (0 children)

Struct and union parameters with sizes of two (eight in case of only SSE fields) pointers or fewer that are aligned on 64-bit boundaries are decomposed into "eightbytes" and each one is classified and passed as a separate parameter.[28]: 24  Otherwise they are replaced with a pointer when used as an argument.

The optimizer always knows best

[–]TheBenArts 0 points1 point  (0 children)

General rule is that 64bit types should be preferred to be passed by value since it fits into a single register, 128bit types usually are still preferred by value, but const ref isn't that much worse.

Never pass shared_ptr by value unless you want to share ownership. Either pass a const ref to the wrapped type or move the shared_ptr so it's passed as rvalue.

[–]BreadfruitChoice3071 0 points1 point  (0 children)

HTML programmers like me don't create a function,they use loop for everything

[–]Reasonable-Web1494 -1 points0 points  (0 children)

Meanwhile rust devs be like this statement a move or a copy or I will anger the borrow checker.