C++ Primer 读书笔记2(二)

2015-01-26 23:13:02 · 作者: · 浏览: 13
/ ok: assigns the value of i to an element in ia3 7 int ia[] = {0,2,4,6,8}; // array with 5 elements of type int int i = ia[2]; // ia is converted to a pointer to the first element in ia // ia[2] fetches the element to which (ia + 2) points int *p = ia; // p points to the first element in ia i = *(p + 2); // equivalent to i = ia[2] int *p = &ia[2]; // p points to the element indexed by 2 int j = p[1]; // p[1] is equivalent to *(p + 1), // p[1] is the same element as ia[3] int k = p[-2]; // p[-2] is the same element as ia[0]

Unlike subscripts for vector and string,the index of the built-in subscript operator is not an unsigned type.

7
string s1 = "A string example"; 
string s2 = "A different string"; 
if (s1 < s2)  // false: s2 is less than s1

const char ca1[] = "A string example"; 
const char ca2[] = "A different string"; 
if (ca1 < ca2)  // undefined: compares two unrelated addresses

For most applications, in addition to beingsafer, it is also more efficient to use library strings rather than C-stylestrings.

8
string s("Hello World");  // s holds Hello World
char *str = s; // error: can't initialize a char* from a string 
const char *str = s.c_str(); // ok

The array returned by c_str is notguaranteed to be valid indefinitely. Any subsequent use of s that might changethe value of s can invalidate this array.

If a program needs continuing access to thecontents of the array returned by str(), the program must copy the arrayreturned by c_str.

9 Advice:Modern C++ programs should use vectors anditerators instead of built-in arrays and pointers, and use strings rather thanC-style array-based character strings.
constexpr size_t rowCnt = 3, colCnt = 4; 
int ia[rowCnt][colCnt];   // 12 uninitialized elements 
// for each row 
for (size_t i = 0; i != rowCnt; ++i) {    // for each column within the row    
for (size_t j = 0; j != colCnt; ++j) {        // assign the element's positional index as its value        ia[i][j] = i * colCnt + j;    
} 
}
《==》
size_t cnt = 0; 
for (auto &row : ia)        // for every element in the outer array
for (auto &col : row) { // for every element in the inner array
        col = cnt;          // give this element the next value
        ++cnt;              // increment cnt
}

In the previous example, we used referencesas our loop control variables because we wanted to change the elements in thearray. However, there is a deeper reason for using references. As an example,consider the following loop:

for (const auto &row : ia)  // for every element in the outer array
for (auto col : row)    // for every element in the inner array
        cout << col << endl;

This loop does not write to the elements,yet we still define the control variable of the outer loop as a reference. Wedo so in order to avoid the normal array to pointer conversion.

Note: To use a multidimensional array in a range for, the loop controlvariable for all but the innermost array must be references.

10 Exercise 3.43: Write three different versions of a program toprint the elements of ia. One version should use a range for to manage theiteration, the other two should use an ordinary for loop in one case usingsubscripts and in the other using pointers. In all three programs write all thetypes directly. That is, do not use a type alias, auto, or decltype to simplifythe code.

Exercise 3.44: Rewrite the programs fromthe previous exercises using a type alias for the type of the loop controlvariables.

Exercise 3.45: Rewrite the programsagain, this time using auto.

	const size_t row = 3;
	const size_t col = 4;
	int arr[row][col];
	int cnt = 0;

	//版本1
	for (int(&p)[4] : arr)
	{
		for (int &q : p)
		{
			q = cnt++;
		}
	}
	for (int(&p)[4] : arr)
	{
		for (int q : p)
		{
			cout << q << " ";
		}
		cout << endl;
	}
	cout << endl;

	//版本2
	for (size_t i = 0; i != row; ++i)
		for (size_t j = 0; j != col; ++j)
			arr[i][j] = i * 4 + j;

	for (size_t i = 0; i != row; ++i)
	{
		for (size_t j = 0; j != col; ++j)
		{
			cout << arr[i][j] << " ";
		}
		cout << endl;
	}
	
	//版本3
	for (int(*p)[4] = arr; p != arr + 3; ++p)
	{
		for (int *q = *p; q != *p + 4; ++q)
		{
			*q = cnt++;
		}
	}

	for (int(*p)[4] = arr; p != arr + 3; ++p)
	{
		for (int *q = *p; q != *p + 4; ++q)
		{
			cout << *q << " ";
		}
		cout << endl;
	}

	//练习3.44
	using int_arr = int[4];
	for (int_arr *p = arr; p != arr + 3; ++p)
	{
		for (int *q = *p; q != *p + 4; ++q)
		{
			*q = cnt++;
		}
	}

	for (int_arr *p = arr; p != arr + 3; ++p)
	{
		for (int *q = *p; q != *p + 4; ++q)
		{
			cout << *q << " ";
		}
		cout << endl;
	}

	//练习3.45
	for (auto &p : arr)
		for (auto &q : p)
			q = cnt++;

	for (auto &p: arr)
	{
		for (auto& q : p)
		{
			cout << q << " ";
		}
		cout << endl;
	}
11 Roughly speaking, when we use an object asan rvalue, we use the object’s value (its contents). When we use an object asan lvalue, we use the object’s identity (its locatio