简体   繁体   中英

Passing temporary objects as argument (C++)

Temporary objects are sometimes created in C++. One example from the STL valarray class would be the slice_array , which is invoked every time a series of indices of a valarray is selected. http://www.cplusplus.com/reference/valarray/slice_array/

My question is this:

When passing these temporary objects as arguments to a function, is a copy of these objects passed, or only a reference?

Eg imagine these two naive functions:

double simple_product(double* inp,int length){
  double res=1;
  for(int i=0;i<length;++i){
      res = res*inp[i];
  }
  return(res);
}

double sum_selected(valarray<double> v){

    simple_product(&v[0],v.size());
    return(v.sum());
}

If I call them in the following fashion:

valarray<double> valery(10,10);
size_t sel[] = {1,3,4};
valarray<size_t> selection (sel,3);
cout << sum_selected(valery[selection]);

will a new object with a size of 3*size_t be temporarily created within the stack of the function sum_selected or not?

Please note that declaring the function as: double sum_selected(valarray<double> & v) is not permitted (temporary objects can only be bound to const references).

The reason why this is interesting is that, for example here, it is not possible to declare the function as:

double sum_selected(const valarray<double> & v) , because then the function simple_product (which is to be assumed unalterable) cannot be called. However, making a temporary copy of the passed argument would be problematic for memory in case of big arrays.

If the function is declared to take its argument by value, then it's passed by value, creating a new copy of the object:

void f(thing t);           // pass by value

If it's declared to take its argument by reference, then it's passed by reference. But it can only take a temporary by const or rvalue reference:

void f(thing const & t);   // OK: const lvalue reference
void f(thing && t);        // OK: rvalue reference
void f(thing & t);         // Error: lvalue reference can't bind to temporary

Passing by reference doesn't create a new object, and the lifetime of the temporary is such that it's valid during the function call, until the end of the statement that creates it.

valarray<T>::operator[](valarray<size_t> const&) returns an indirect_array<T> ( reference ), or a valarray<T> for the const -qualified operator, not a slice_array .

If you want to be able to access the selected elements as a contiguous array, then you'll need to collect them into a contiguous array. The converting constructor valarray<T>::valarray(indirect_array<T> const&) does this for you. Reference semantics would be useless in this case, as there is no existing object that has your desired elements arranged contiguously.

Changing the function signature to double sum_selected(valarray<double> const&) would make no difference to your code, as a temporary valarray<double> is constructed anyway. It would be more efficient in the case where valery is passed directly, without subscripting.

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