Professional C__ - Marc Gregoire [140]
Move constructors and move assignment operators can also be explicitly deleted or defaulted, just like normal constructors and normal copy assignment operators, as explained in Chapter 6.
As another example where move semantics increases performance, take a swap() function that swaps two objects. Before C++11, a swap() function could be implemented as follows. This example uses templates, which are discussed in detail in Chapter 19.
template void swapCopy(T& a, T& b) { T temp(a); a = b; b = temp; } This implementation first copies a to temp, then copies b to a and then copies temp to b. If type T is expensive to copy, this swap implementation will hurt performance. With move semantics the swap() function can avoid all copying: template void swapMove(T& a, T& b) { T temp(std::move(a)); a = std::move(b); b = std::move(temp); } Obviously, move semantics is useful only when you know that the source object will be destroyed. KEYWORD CONFUSION The const Keyword The keyword const is short for “constant” and specifies that something remains unchanged. The compiler will enforce this requirement by marking any attempt to change it as an error. Furthermore, when optimizations are enabled, the compiler can take advantage of this knowledge to produce better code. The keyword const has two related roles. It can mark variables or parameters, and it can mark methods. This section provides a definitive discussion of these two meanings. const Variables and Parameters You can use const to “protect” variables by specifying that they cannot be modified. As Chapters 1 and 5 explain, one important use of this keyword is as a replacement for #define to declare constants. This use of const is its most straightforward application. For example, you could declare the constant PI like this: const double PI = 3.14159; Code snippet from Const\Const.cpp You can mark any variable const, including global variables and class data members. You can also use const to specify that parameters to functions or methods should remain unchanged. For example, the following function accepts a const parameter. In the body of the function, you cannot modify the param integer. If you do try to modify it, the compiler will generate an error. void func(const int param) { // Not allowed to change param... } Code snippet from Const\Const.cpp The following subsections discuss two special kinds of const variables or parameters in more detail: const pointers and const references. const Pointers When a variable contains one or more levels of indirection via a pointer, applying const becomes trickier. Consider the following lines of code: int* ip; ip = new int[10]; ip[4] = 5; Code snippet from Const\Const.cpp Suppose that you decide to apply const to ip. Set aside your doubts about the usefulness of doing so for a moment, and consider what it means. Do you want to prevent the ip variable itself from being changed, or do you want to prevent the values to which it points from being changed? That is, do you want to prevent the second line or the third line in the previous example? In order to prevent the pointed-to value from being modified (as in the third line), you can add the keyword const to the declaration of ip like this: const int* ip; ip = new int[10]; ip[4] = 5; // DOES NOT COMPILE! Code snippet from Const\Const.cpp Now you cannot change the values to which ip points. An alternative, but semantically equivalent way
Two keywords in C++ appear to cause more confusion than any others: const and static. Both of these keywords have several different meanings, and each of their uses presents subtleties that are important to understand.