Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ view types: pass by const& or by value?

This came up in a code review discussion recently, but without a satisfactory conclusion. The types in question are analogues to the C++ string_view TS. They are simple non-owning wrappers around a pointer and a length, decorated with some custom functions:

#include <cstddef>  class foo_view { public:     foo_view(const char* data, std::size_t len)         : _data(data)         , _len(len) {     }      // member functions related to viewing the 'foo' pointed to by '_data'.  private:     const char* _data;     std::size_t _len; }; 

The question arose as to whether there is an argument either way to prefer to pass such view types (including the upcoming string_view and array_view types) by value or by const reference.

Arguments in favor of pass by value amounted to 'less typing', 'can mutate the local copy if the view has meaningful mutations', and 'probably no less efficient'.

Arguments in favor of pass-by-const-reference amounted to 'more idiomatic to pass objects by const&', and 'probably no less efficient'.

Are there any additional considerations that might swing the argument conclusively one way or the other in terms of whether it is better to pass idiomatic view types by value or by const reference.

For this question it is safe to assume C++11 or C++14 semantics, and sufficiently modern toolchains and target architectures, etc.

like image 840
acm Avatar asked Dec 02 '14 18:12

acm


People also ask

Does C support pass by constant reference?

C does not support references or passing by reference. You should use pointers instead and pass by address. Pass-by-value is efficient for primitive types, but does a shallow copy for structs. In C++ it makes a LOT of sense to pass objects by reference for efficiency.

What is the difference between pass by reference and pass by const reference?

From what I understand: when you pass by value, the function makes a local copy of the passed argument and uses that; when the function ends, it goes out of scope. When you pass by const reference, the function uses a reference to the passed argument that can't be modified.

Should String_view be passed by reference?

So, frequently, you can pass string_view by reference and get away with it. But you should pass string_view by value, so that the compiler doesn't have to do those heroics on your behalf. And so that your code-reviewer doesn't have to burn brain cells pondering your unidiomatic decision to pass by reference.

What does pass by const reference mean?

Passing By Reference To Const in C++ Passing By Reference To Const in C++ C++ is an example of a message-passing paradigm language, which means that objects and values are passed to functions, which then return further objects and values based on the input data.


1 Answers

When in doubt, pass by value.

Now, you should only rarely be in doubt.

Often values are expensive to pass and give little benefit. Sometimes you actually want a reference to a possibly mutating value stored elsewhere. Often, in generic code, you don't know if copying is an expensive operation, so you err on the side of not.

The reason why you should pass by value when in doubt is because values are easier to reason about. A reference (even a const one) to external data could mutate in the middle of an algorithm when you call a function callback or what have you, rendering what seems to be a simple function into a complex mess.

In this case, you already have an implicit reference bind (to the contents of the container you are viewing). Adding another implicit reference bind (to the view object that looks into the container) is no less bad because there are already complications.

Finally, compilers can reason about values better than they can about references to values. If you leave the locally analyzed scope (via a function pointer callback), the compiler has to presume the value stored in the const reference may have completely changed (if it cannot prove the contrary). A value in automatic storage with nobody taking a pointer to it can be assumed to not modify in a similar way -- there is no defined way to access it and change it from an external scope, so such modifications can be presumed to not-happen.

Embrace the simplicity when you have an opportunity to pass a value as a value. It only happens rarely.

like image 176
Yakk - Adam Nevraumont Avatar answered Sep 27 '22 21:09

Yakk - Adam Nevraumont