频道栏目
首页 > 资讯 > C++ > 正文

C++ Primer 读书笔记2

14-12-06        来源:[db:作者]  
收藏   我要投稿

1 Reada set of integers into a vector. Print the sum of each pair of adjacent elements.Change your program so that it prints the sum of the first and last elements,followed by the sum of the second and second-to- last, and so on.

        vector ivect;
	int value;
	
	while (cin >> value)
	{
		ivect.push_back(value);
	}
	for (decltype(ivect.size()) idx = 0; idx < ivect.size() - 1; idx += 2)
	{
		cout << ivect[idx] + ivect[idx + 1] << endl;
	}
	if (ivect.size() % 2 == 1)
		cout << ivect[ivect.size() - 1] << endl;

	//用迭代器实现
	vector ivect;
	int value;
	
	while (cin >> value)
	{
		ivect.push_back(value);
	}
	auto iter = ivect.begin();
	for (; (iter != ivect.end()) && ((iter + 1) != ivect.end()); iter += 2)
	{
		cout << *iter + *(iter + 1) << " ";
	}
	if (iter != ivect.end())
	{
		cout << *iter << endl;
	}

	vector ivect;
	int value;
	
	while (cin >> value)
	{
		ivect.push_back(value);
	}
	decltype(ivect.size()) i = 0, j = ivect.size() - 1;
	for (; i < j; ++i, --j)
	{
		cout << ivect[i] + ivect[j] << endl;
	}
	if (i == j)
	{
		cout << ivect[i] << endl;
	}

	//用迭代器实现
	vector ivect;
	int value;
	
	while (cin >> value)
	{
		ivect.push_back(value);
	}
	auto ibegin = ivect.begin(), iend = ivect.end() - 1;
	for (; ibegin < iend; ++ ibegin, -- iend)
	{
		cout << *ibegin + *iend << " ";
	}
	if (ibegin == iend)
	{
		cout << *ibegin << endl;
	}

2 Allof the library containers have iterators, but only a few of them support thesubscript operator. C++ programmers use != as a matter of habit. They do so forthe same reason that they use iterators rather than subscripts: This codingstyle applies equally well to various kinds of containers provided by thelibrary. As we’ve seen, only a few library types, vector and string being amongthem, have the subscript operator. Similarly, all of the library containershave iterators that define the == and != operators. Most of those iterators donot have the < operator. By routinely using iterators and !=, we don’t haveto worry about the precise type of container we’re processing.

3 Thetype returned by begin and end depends on whether the object on which theyoperator is const. If the object is const, then begin and end return aconst_iterator; if the object is not const, they return iterator:

vector v; 
const vector cv; 
auto it1 = v.begin();  // it1 has type vector::iterator 
auto it2 = cv.begin(); // it2 has type vector::const_iterator

auto it3 = v.cbegin(); // it3 has type vector::const_iterator

As do the begin and end members, thesemembers return iterators to the first and one past the last element in thecontainer. However, regardless of whether the vector (or string) is const, theyreturn a const_iterator.

4 Asa result, the dimension must be known at compile time, which means that thedimension must be a constant expression:

unsigned cnt = 42;          // not a constant expression 
constexpr unsigned sz = 42; // constant expression                           
int arr[10];             // array of ten ints
int *parr[sz];           // array of 42 pointers to int 
string bad[cnt];         // error: cnt is not a constant expression 
string strs[get_size()]; // ok if get_size is constexpr, error otherwise

When we define an array, we must specify atype for the array. We cannot use auto to deduce the type from a list ofinitializers. As with vector, arrays hold objects. Thus, there are no arrays ofreferences.

5 Whenwe use a variable to subscript an array, we normally should define thatvariable to have type size_t. size_t is a machine-specific unsigned type thatis guaranteed to be large enough to hold the size of any object in memory. Thesize_t type is defined in the cstddef header, which is the C++ version of thestddef.h header from the C library.
6
string nums[] = {"one", "two", "three"};  // array of strings 
string *p = &nums[0];   // p points to the first element in nums
string *p2 = nums;      // equivalent to p2 = &nums[0]

int ia[] = {0,1,2,3,4,5,6,7,8,9}; // ia is an array of ten ints 
auto ia2(ia); // ia2 is an int* that points to the first element in ia 
ia2 = 42;     // error: ia2 is a pointer, and we can't assign an int to a pointer
auto ia2(&ia[0]);  // now it's clear that ia2 has type int*

// ia3 is an array of ten ints 
decltype(ia) ia3 = {0,1,2,3,4,5,6,7,8,9};
ia3 = p;    // error: can't assign an int* to an array 
ia3[4] = i; // 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 location in memory).

Lvalues and rvalues also differ when usedwith decltype. When we apply decltype to an expression (other than a variable),the result is a reference type if the expression yields an lvalue. As anexample, assume p is an int*. Because dereference yields an lvalue,decltype(*p) is int&. On the other hand, because the address-of operatoryields an rvalue, decltype(&p) is int**, that is, a pointer to a pointer totype int.&Pg121

12 Moreover,except for the obscure case where -m overflows, (-m)/n and m/(-n) are alwaysequal to -(m/n).
13
//  note s as a reference to const; the elements aren't copied and can't be changed 
for (const auto &s : text) { // for each element in text
cout << s;        // print the current element
// blank lines and those that end with a period get a newline
    if (s.empty() || s[s.size() - 1] == '.')
        cout << endl;
    else
        cout << " ";  // otherwise just separate with a space
}
14

// the behavior of the following loop is undefined! 
while (beg != s.end() && !isspace(*beg))
*beg = toupper(*beg++);   // error: this assignment is undefined


相关TAG标签
上一篇:Java数据结构系列之——树(4):二叉树的中序遍历的递归与非递归实现
下一篇:NYOJ 527 AC_mm玩dota
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站