C++ Tutorial/Data Types/reference
Содержание
- 1 Assign value to a reference-return
- 2 Change reference value
- 3 class for counted reference semantics
- 4 constant references
- 5 Creating and Using References
- 6 Reassigning a reference
- 7 References must be initialized
- 8 Return a reference to an array element.
- 9 Returning a reference
- 10 Use an independent reference.
- 11 Use reference as a return type
- 12 Use References operator &
- 13 Use reference to swap value
Assign value to a reference-return
<source lang="cpp">#include <iostream> using namespace std;
double &f();
double val = 100.0;
int main() {
double x; f() = 99.1; cout << f() << "\n"; return 0;
}
double &f() {
return val; // return reference to val
}</source>
99.1
Change reference value
<source lang="cpp">#include <iostream.h> main() {
int a[] = {1,3,5,7,9}; int i=2 ; int &r = a[i]; cout <<r<<endl; r=99; cout <<a[i]<<endl; return 0;
}</source>
5 99
class for counted reference semantics
<source lang="cpp">/* The following code example is taken from the book
* "The C++ Standard Library - A Tutorial and Reference" * by Nicolai M. Josuttis, Addison-Wesley, 1999 * * (C) Copyright Nicolai M. Josuttis 1999. * Permission to copy, use, modify, sell and distribute this software * is granted provided this copyright notice appears in all copies. * This software is provided "as is" without express or implied * warranty, and with no claim as to its suitability for any purpose. */
- include <iostream>
- include <list>
- include <deque>
- include <algorithm>
using namespace std; /* class for counted reference semantics
* - deletes the object to which it refers when the last CountedPtr * that refers to it is destroyed */
template <class T> class CountedPtr {
private: T* ptr; // pointer to the value long* count; // shared number of owners public: // initialize pointer with existing pointer // - requires that the pointer p is a return value of new explicit CountedPtr (T* p=0) : ptr(p), count(new long(1)) { } // copy pointer (one more owner) CountedPtr (const CountedPtr<T>& p) throw() : ptr(p.ptr), count(p.count) { ++*count; } // destructor (delete value if this was the last owner) ~CountedPtr () throw() { dispose(); } // assignment (unshare old and share new value) CountedPtr<T>& operator= (const CountedPtr<T>& p) throw() { if (this != &p) { dispose(); ptr = p.ptr; count = p.count; ++*count; } return *this; } // access the value to which the pointer refers T& operator*() const throw() { return *ptr; } T* operator->() const throw() { return ptr; } private: void dispose() { if (--*count == 0) { delete count; delete ptr; } }
};
void printCountedPtr (CountedPtr<int> elem) {
cout << *elem << " ";
} int main() {
// array of integers (to share in different containers) static int values[] = { 3, 5, 9, 1, 6, 4 }; // two different collections typedef CountedPtr<int> IntPtr; deque<IntPtr> coll1; list<IntPtr> coll2; /* insert shared objects into the collections * - same order in coll1 * - reverse order in coll2 */ for (int i=0; i<sizeof(values)/sizeof(values[0]); ++i) { IntPtr ptr(new int(values[i])); coll1.push_back(ptr); coll2.push_front(ptr); } // print contents of both collections for_each (coll1.begin(), coll1.end(),printCountedPtr); cout << endl; for_each (coll2.begin(), coll2.end(),printCountedPtr); cout << endl << endl; /* modify values at different places * - square third value in coll1 * - negate first value in coll1 * - set first value in coll2 to 0 */ *coll1[2] *= *coll1[2]; (**coll1.begin()) *= -1; (**coll2.begin()) = 0; // print contents of both collections again for_each (coll1.begin(), coll1.end(),printCountedPtr); cout << endl; for_each (coll2.begin(), coll2.end(),printCountedPtr); cout << endl;
}</source>
3 5 9 1 6 4 4 6 1 9 5 3 -3 5 81 1 6 0 0 6 1 81 5 -3
constant references
<source lang="cpp">#include <iostream>
- include <string>
- include <vector>
using namespace std; void display(const vector<string>& inventory); int main() {
vector<string> inventory; inventory.push_back("sword"); inventory.push_back("armor"); inventory.push_back("shield"); display(inventory); return 0;
} void display(const vector<string>& vec) {
cout << "Your items:\n"; for (vector<string>::const_iterator iter = vec.begin(); iter != vec.end(); ++iter) cout << *iter << endl;
}</source>
Creating and Using References
<source lang="cpp">#include <iostream>
int main() { int intValue; int &intReference = intValue; intValue = 5; std::cout << "intValue: " << intValue << std::endl; std::cout << "intReference: " << intReference << std::endl; intReference = 7; std::cout << "intValue: " << intValue << std::endl; std::cout << "intReference: " << intReference << std::endl; return 0; }</source>
intValue: 5 intReference: 5 intValue: 7 intReference: 7
Reassigning a reference
<source lang="cpp">#include <iostream>
using namespace std; int main() { int intValue; int &intReference = intValue; intValue = 5; cout << "intValue:\t" << intValue << endl; cout << "intReference:\t" << intReference << endl; cout << "&intValue:\t" << &intValue << endl; cout << "&intReference:\t" << &intReference << endl; int intTwo = 8; intReference = intTwo; // not what you think! cout << "\nintValue:\t" << intValue << endl; cout << "intTwo:\t" << intTwo << endl; cout << "intReference:\t" << intReference << endl; cout << "&intValue:\t" << &intValue << endl; cout << "&intTwo:\t" << &intTwo << endl; cout << "&intReference:\t" << &intReference << endl; return 0; }</source>
intValue: 5 intReference: 5 &intValue: 0x22ff74 &intReference: 0x22ff74 intValue: 8 intTwo: 8 intReference: 8 &intValue: 0x22ff74 &intTwo: 0x22ff6c &intReference: 0x22ff74
References must be initialized
<source lang="cpp">#include <iostream> using std::cout; using std::endl; int main() {
int x = 321; int &y = x; cout << "x = " << x << " y = " << y << endl; y = 123; cout << "x = " << x << " y = " << y << endl; return 0;
}</source>
x = 321 y = 321 x = 123 y = 123
Return a reference to an array element.
<source lang="cpp">#include <iostream> using namespace std;
double &f(int i); // return a reference
double vals[] = { 1.1, 2.2, 3.3, 4.4, 5.5 };
int main() {
int i; cout << "Here are the original values: "; for(i=0; i < 5; i++) cout << vals[i] << " "; f(1) = 8.23; // change 2nd element f(3) = -8.8; // change 4th element cout << "\nHere are the changed values: \n"; for(i=0; i < 5; i++) cout << vals[i] << " "; return 0;
}
double &f(int i) {
return vals[i]; // return a reference to the ith element
}</source>
Here are the original values: 1.1 2.2 3.3 4.4 5.5 Here are the changed values: 1.1 8.23 3.3 -8.8 5.5
Returning a reference
<source lang="cpp">#include <iostream> using namespace std;
double &f();
double val = 100.0;
int main() {
double x; cout << f() << "\n"; x = f(); // assign value of val to x cout << x << "\n"; return 0;
}
double &f() {
return val; // return reference to val
}</source>
100 100
Use an independent reference.
<source lang="cpp">#include <iostream> using namespace std;
int main() {
int j, k; int &i = j; // independent reference j = 10; cout << j << " " << i; // outputs 10 10 k = 121; i = k; // copies k"s value into j, not k"s address cout << "\n" << j; // outputs 121 return 0;
}</source>
10 10 121
Use reference as a return type
<source lang="cpp">#include <iostream.h> int& Fn(int * p,int i); main() {
const int S=4; int a[S] = {1,3,5,-1}; for (int j = 0; j<S; j++) { Fn(a,j) += 1; cout << Fn(a,j) << endl; } return 0;
} int& Fn(int * p,int i){
return p[i];
}</source>
2 4 6 0
Use References operator &
<source lang="cpp">#include <iostream> int main() {
int intValue; int &intReference = intValue; intValue = 5; std::cout << "intValue: " << intValue << std::endl; std::cout << "intReference: " << intReference << std::endl; std::cout << "&intValue: " << &intValue << std::endl; std::cout << "&intReference: " << &intReference << std::endl; return 0;
}</source>
intValue: 5 intReference: 5 &intValue: 0x22ff74 &intReference: 0x22ff74
Use reference to swap value
<source lang="cpp">#include <iostream.h> void Swap(int& x,int& y); int main(void) {
int n1 = 1, n2 = 2; Swap(n1,n2); cout << n1 << " " << n2 << endl;
} void Swap(int& x,int& y) {
int t = x; x = y; y = t;
}</source>
2 1