Online Book Reader

Home Category

Professional C__ - Marc Gregoire [137]

By Root 1355 0
that the function can change the actual pointers, and the address of two ints so that the function can change the actual ints:

int unSplit[10] = {1, 2, 3, 4, 5, 6, 6, 8, 9, 10};

int *oddNums, *evenNums;

int numOdds, numEvens;

separateOddsAndEvens(unSplit, 10, &oddNums, &numOdds, &evenNums, &numEvens);

Code snippet from References\OddsEvensPtrs.cpp

If such syntax annoys you (which it should), you can write the same function by using references to obtain true pass-by-reference semantics:

void separateOddsAndEvens(const int arr[], int size, int*& odds,

int& numOdds, int*& evens, int& numEvens)

{

numOdds = numEvens = 0;

for (int i = 0; i < size; i++) {

if (arr[i] % 2 == 1) {

numOdds++;

} else {

numEvens++;

}

}

odds = new int[numOdds];

evens = new int[numEvens];

int oddsPos = 0, evensPos = 0;

for (int i = 0; i < size; i++) {

if (arr[i] % 2 == 1) {

odds[oddsPos++] = arr[i];

} else {

evens[evensPos++] = arr[i];

}

}

}

Code snippet from References\OddsEvensRefs.cpp

In this case, the odds and evens parameters are references to int*s. separateOddsAndEvens() can modify the int*s that are used as arguments to the function (through the reference), without any explicit dereferencing. The same logic applies to numOdds and numEvens, which are references to ints.

With this version of the function, you no longer need to pass the addresses of the pointers or ints. The reference parameters handle it for you automatically:

int unSplit[10] = {1, 2, 3, 4, 5, 6, 6, 8, 9, 10};

int *oddNums, *evenNums;

int numOdds, numEvens;

separateOddsAndEvens(unSplit, 10, oddNums, numOdds, evenNums, numEvens);

Code snippet from References\OddsEvensRefs.cpp

It’s recommended to avoid dynamically allocated arrays as much as possible to make your life easier. For example, by using the STL vector container, the previous separateOddsAndEvens() can be rewritten much more compactly and elegantly, because all memory allocation and deallocation happens automatically.

void separateOddsAndEvens(const vector& arr,

vector& odds, vector& evens)

{

for (auto& i : arr) {

if (i % 2 == 1)

odds.push_back(i);

else

evens.push_back(i);

}

}

Code snippet from References\OddsEvensVector.cpp

This version can be used as follows:

vector vecUnSplit = {1, 2, 3, 4, 5, 6, 6, 8, 9, 10};

vector odds, evens;

separateOddsAndEvens(vecUnSplit, odds, evens);

Code snippet from References\OddsEvensVector.cpp

The STL vector container is discussed in more detail in Chapter 12.

Rvalue References

In C++, an lvalue is something of which you can take an address, a named variable for example. The name comes from the fact that they normally appear on the left-hand side of an assignment. An rvalue on the other hand is anything that is not an lvalue, a constant value for example or a temporary object or value. Typically an rvalue is on the right-hand side of an assignment operator.

C++11 introduces a new concept, an rvalue reference, which is a reference to an rvalue. In particular, it is a concept that is applied when the rvalue is a temporary object. The purpose of an rvalue reference is to allow methods (most particularly, but not restricted to, copy constructors and operator=) so that a particular method can be chosen when a temporary object is involved. The consequence of this is that certain operations which normally involve copying large values can be implemented by simply copying pointers to those values, knowing the temporary object will be destroyed.

A method can specify an rvalue reference parameter by using && as part of the parameter specification, e.g., type&& name. Normally, a temporary object will be seen as a const type&, but when there is a method that uses an rvalue reference, a temporary object can be resolved to this overload.

However, rvalue references are not limited to parameters of functions. You can declare a variable of type rvalue reference, and assign to it, although this usage is uncommon. Consider the following code, which is illegal in C++:

int& i = 2; // Invalid: reference to a constant

Return Main Page Previous Page Next Page

®Online Book Reader