抄来的

http://www.cnblogs.com/zzj3/

左值lvalue 和 右值rvalue

1、lvalue: An expression that is an lvalue may appear as either the left-hand or right-hand side of an assignment.

2、rvalue: An expression that is an rvalue may appear on the right-hang but not left-hand side of an assignment.

Variables are lvalues and so may appear on the left-hand side of an assignment. Numeric literals are rvalues and so may not be assigned.

引用reference

reference serves as an alternative name for an object. In real-world programs, references are primarily used as formal parameters to functions.

Each reference type "refers to" some other type. We cannot define a reference to a reference type, but can make a reference to any other data type.

A reference must be initialized using an object of the same type as the reference:

int ival = 1024;
int &refVal = ival; // ok: refVal refers to ival
int &refVal2;       // error: a reference must be initialized
int &refVal3 = 10;  // error: initializer must be an object

Because a reference is just another name for the object to which it is bound, all operations on a reference are actually operations on the underlying object to which the reference is bound.

When a reference is initialized, it remains bound to that object as long as the reference exists. There is no way to rebind a reference to a different object.

A consequence of this rule is that you must initialize a reference when you define it; initialization is the only way to say to which object a reference refers.

A const reference is a reference that may refer to a const object:

const int ival = 1024;
const int &refVal = ival; // ok: both reference and object are const
int &ref2 = ival;         // error: non const reference to a const object

We should know that const Reference is a Reference to const.

A const reference can be initialized to an object of a different type or to an rvalue, such as a literal constant:

int i = 42;
// legal for const references only
const int &r = 42;
const int &r2 = r + i;

The same initializations are not legal for nonconst references. 

This behavior is easiest to understand when we look at what happens when we bind a reference to an object of a different type. If we write

double dval = 3.14;
const int &ri = dval;

the compiler transforms this code into something like this:

int temp = dval; // create temporary int from the double
const int &ri = temp; // bind ri to that temporary

If ri were not const , then we could assign a new value to ri . Doing so would not change dval but would instead change temp . To the programmer expecting that assignments to ri would change dval , it would appear that the change did not work. Allowing only const references to be bound to values requiring temporaries avoids the problem entirely because a const reference is read-only.

A nonconst reference may be attached only to an object of the same type as the reference itself.

A const reference may be bound to an object of a different but related type or to an rvalue.

参数传递(non reference parameter)

C++ is a statically typed language. The arguments of every call are checked during compilation.

int gcd(int v1, int v2);

But what happens if the call supplies two arguments of type double ? Is this call legal?

gcd("hello", "world"); // error: wrong argument types
gcd(3.14, 6.29);       // ok: arguments are converted to int

In the first call, the arguments are of type const char* .

In the second call, because this conversion might lose precision, most compilers will issue a warning. In this case, the call becomes

gcd(3, 6);

-----------------------------------------------------------------------------------------------------------------------------

If the parameter has a nonreference type, then the argument is copied. If the parameter is a reference, then the parameter is just another name for the argument.

We may initialize a pointer to const to point to a non const object but may not use a pointer to non const to point to a const object.

We can call a function that takes a non reference, non const parameter passing either a const or non const argument.

If we make the parameter a const nonreference type:

void fcn(const int i) { /* fcn can read but not write to i */ }

The argument is still passed as a copy so we can pass fcn either a const or non const object.

What may be surprising, is that although the parameter is a const inside the function, the compiler otherwise treats the definition of fcn as if we had defined the parameter as a plain int

 

复制代码
void fcn(const int i) { /* fcn can read but not write to i */ }
void fcn(int i) {}     // error: redefines fcn(int)

void fcn(const int &i) {}
void fcn(int &i) {}         // OK

void fcn(const int *i) {}
void fcn(int *i) {}        // OK

void fcn(int * const i) {}
void fcn(int *i) {}       // error
// 从调用者的角度分析,第一个函数只能传递给它非常量,第二个函数是同样的。所以发生重复定义错误。
复制代码

Copying an argument is not suitable for every situation. Cases where copying doesn't work include:
1、When we want the function to be able to change the value of an argument.
2、When we want to pass a large object as an argument. The time and space costs to copy the object are often too high for real-world applications.
3、When there is no way to copy the object.
In these cases we can instead define the parameters as references or pointers.

参数传递(reference parameter)

Programmers who come to C++ from a C background are used to passing pointers to obtain access to the argument. In C++ it, is safer and more natural to use reference parameters.

It should be obvious that a function that takes a plain, nonconst reference may not be called on behalf of a const object. After all, the function might change the object it is passed and thus violate the const ness of the argument. What may be less obvisous is that we also cannot call such a function with an rvalue or with an object of a type that requires a conversion:

复制代码
// function takes a non-const reference parameter
int incr(int &val)
{
     return ++val;
}
int main()
{
     short v1 = 0;
     const int v2 = 42;
     int v3 = incr(v1); // error: v1 is not an int
     v3 = incr(v2); // error: v2 is const
     v3 = incr(0); // error: literals are not lvalues
     v3 = incr(v1 + v2); // error: addition doesn't yield an lvalue
     int v4 = incr(v3); // ok: v3 is a non const object type int
}
复制代码

Parameters that do not change the value of the corresponding argument should be const references.

复制代码
// returns index of first occurrence of c in s or s.size() if c isn't in s
// Note: s doesn't change, so it should be a reference to const
string::size_type find_char(string &s, char c)
{
      string::size_type i = 0;
      while (i != s.size() && s[i] != c)
            ++i;                    // not found, look at next character
      return i;
}
复制代码

This function takes its string argument as a plain (nonconst) reference, even though it doesn't modify that parameter. One problem with this definition is that we cannot call it on a character string literal:

if (find_char("Hello World", 'o')) // ...

Best practices:Reference parameters that are not changed should be references to const . Plain, nonconst reference parameters are less flexible. Such parameters may not be initialized by const objects, or by arguments that are literals or expressions that yield rvalues.

int *&v1;    // v1 is a reference to a pointer to an object of type int .

 

In order to avoid copying the vector , we might think that we'd make the parameter a reference. In practice, C++ programmers tend to pass containers by passing iterators to the elements we want to process:

复制代码
// pass iterators to the first and one past the last element to print
void print(vector<int>::const_iterator beg,
vector<int>::const_iterator end)
{
      while (beg != end) {
            cout << *beg++;
      if (beg != end) cout << " "; // no space after last element
      }
      cout << endl;
}
复制代码

 

posted @ 2015-06-13 11:10  仩僐婼渁  阅读(105)  评论(0编辑  收藏  举报