Frage

I need to pass a non-POD type to a C++ function. I want to modify the value inside that function, but I don't want that change to be visible outside of that function.

My first option is to pass by value, which creates a copy.

void myFunction (NonSimpleObject foo) {
  foo = ~foo;
}

I could also pass by reference, which is faster during function calling, but I would need to create a copy inside to not influence the outside value;

void myFunction (NonSimpleObject &foo) {
  NonSimpleObject foo_internal = ~foo;      
}

To signal to the caller that I will not modify the outside value, I would like to include a const qualifier. This is of course implicit when calling by value, but I would like to be more verbose. But passing a const value will force me to create a second copy inside to modify the value, which also is somewhat the opposite of what the const qualifier is used for originally.

void myFunction (const NonSimpleObject foo) {
  NonSimpleObject foo_internal = ~foo;
}

Passing a const reference will both signal to the caller that the outside value is not changed as well as only requiring one copy inside the function.

void myFunction (const NonSimpleObject &foo) {
  NonSimpleObject foo_internal = ~foo;      
}

Which one is the best to use for my purpose (good performance, verbose to the caller) and what would be the advantages/disadvantages?

This also boils down to the questions: Is there any advantage to copying inside a function instead of copying during parameter passing or vice versa?

War es hilfreich?

Lösung

If you need a local object, then passing by value is best. This enables move semantics, if the argument is a temporary or explicitly moved, so that unnecessary copying can be avoided.

Passing by reference forces a copy whether it's needed or not. If the reference isn't const, then the argument can't be a temporary. Accepting a const object by value and then copying it is just weird.

(Note that, in your specific examples, you don't need a local copy, just the result of applying an operator to the argument; so a const reference might be more appropriate.)

Andere Tipps

Just pass it by value:

  • It creates a copy (and spares you the need to write any code for it, i.e. an explicit copy)
  • Regarding your concern about the semantics of what you're doing : an argument passed by value makes it clear to the calling code that you're not modifying the object inside the function, that you created a copy of it, and that the original object will remain untouched. const is better used when it's the actual object you're passing to the function (i.e. with a reference) and that you want it not to be modified (e.g. just to "peek" at it).
  • Passing by reference would need that you manually create a copy, which is done with passing it by value.

So, this way:

void myFunction (NonSimpleObject foo) {
   //modify foo here
}

The first case (void myFunction (NonSimpleObject foo)) is going to create two objects. The first object is foo and the second foo_internal.

The second case (void myFunction (const NonSimpleObject &foo)) is going to create only one object - that is foo_internal.

Therefore, the second case is better.

Is there any advantage to copying inside a function instead of copying during parameter passing or vice versa?

If you are going to use created object, then do copy it. You didn't show enough code to tell if the copy is needed or not. As far as it stands right now - I would say use const reference.

"I want to modify the value inside that function, but I don't want that change to be visible outside of that function."

Then you mean changing a local copy of the object. (I don't think you mean a friend-function which allows you to change private data of an object.)

So you need passing by-value and the most clean solution is your 1. (and not by reference, and then making inside a local copy (your 2. solution)).

This signalizes the user, that the passed object will not be changed (only its local copy, but that's what you want). Passing it by-value to a const (your 3. solution) is slightly different: you not only signalize the user, that the passed object won't be changed, but also that the local copy is unchangable.

Passing it by const reference signalizes, that the passed object will neither be changed nor there exists a changable local copy.

So you should think about what you really want.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top