Earlier, someone posted a question about std::clamp but the thread was removed before I had a chance to respond (probably because the OP realized his mistake).
The result was stored as a reference. It was OK in this case because all the arguments were variables but I just wanted to point out that one should be careful when storing the result of std::clamp as a reference (same with std::max/std::min) because if you instead pass literals (temporaries) then they would get destroyed at the end of the statement and you would end up with a dangling reference.
1 2 3
int number = 21;
constint &p = std::clamp(number, 10, 20);
std::cout << p << "\n"; // Undefined behaviour! (p refers to the temporary object created by the literal 20 which no longer exists)
There were no real need to store the result as a reference, and I can't remember when I have ever needed it, so I would say it's probably best to avoid it. A situation where you might want to do it is if you're using it with a class type that cannot be copied or that is costly to copy.
So in this case, the lifetime of the object created by the int literal isn't extended due to the 'const T&' type of p?
The lifetime is not extended.
A const ref only extends the lifetime if you bind it to the temporary directly.
It does not work with functions that return references.
There is one simple rule which helps to avoid such issues without knowing all the internals of the standard, which is that POD's should be treated as POD's.
for ex. POD data should not never be const by reference in function parameters since you gain 0 performance benefit from that.
std::clamp always takes the arguments by reference and returns a reference no matter what type it is. It's not something we can change unless we write our own clamp function (template).
How exactly is the first version better or faster?
it's a waste of keystrokes to write that const and &
it's just an int, it won't hurt if it gets copied and the compiler will optimize it anyway..
However: void f(int& param);
Is a different story, obviously you need a reference here by design!
The 'rule of thumb' is to use const ref where the size of the data to be passed is greater than the size of a pointer - as behind the scene refs are passed as pointers. So for 64-bit, anything with a size less 9 bytes pass by value otherwise pass by const ref.
We could be in agreement, I just don't understand that sentence.
My mistake because in language grammar POD's aren't just int's, floats and similar but also structs which may do things such as your example, but I was referring to built in data types.
@seeplus, that's good rule, It's easy to remember it.
Since passing by const reference is that similar to passing by value i would guess that the compiler may generate the same binary for both (whatever is shorter: the value or the reference/pointer).