《C++ Primer》5th 課後練習 第六章 函數 11~20

練習 6.11 編寫並驗證你自己的reset函數,使其作用於引用類型的參數。

#include<iostream>
using namespace std;
void reset(int &a) {
	a = 0;
}
int main()
{
	int x = 10;
	cout << "x: " << x << endl;
	reset(x);
	cout << "x: " << x << endl;
	return 0;
}

練習 6.12 改寫6.2.1節練習中的程序,使其引用而非指針交換兩個整數的值。你覺得哪種方法更易於使用呢?爲什麼?

#include<iostream>
using namespace std;
void swap(int &a, int &b) {
	int tmp = a;
	a = b;
	b = tmp;
	return;
}
int main()
{
	int a = 1, b = 2;
	cout << "a: " << a << "\nb: " << b << endl;
	swap(a, b);
	cout << "a: " << a << "\nb: " << b << endl;
	return 0;
}

顯然引用更好。

練習 6.13 假設 T 是某種類型的名字,說明以下兩個函數聲明的區別:一個是void f(T), 另一個是 void f(&T)

前者是傳值,不能通過形參改變實參。

後者是傳引用,可以通過形參改變實參。

ps:我覺得後面的那種寫法應該是 void f(T &),直接用樹上的寫法會編譯出錯。

練習 6.14 舉一個形參應該是引用類型的例子,再舉一個形參不能是引用類型的例子。

交換兩個變量的數值,形參需要用引用類型。

當不希望函數改變實參的值而函數中又會更改形參的值時,則形參不能用引用類型。

練習 6.15 說明find_char 函數中的三個形參爲什麼是現在的類型,特別說明爲什麼s是常量引用而occurs是普通引用?爲什麼soccurs是引用類型而c不是?如果令s是普通引用會發生什麼情況?如果令occurs是常量引用會發生什麼情況?

  • 使用傳值方式的話,字符串複製的開銷很大,所以傳入引用;因爲函數保證不會修改s的值,所以用const引用來加以限制。
  • 因爲調用者是通過occurs來隱式地獲得c的出現次數的,所以需要函數在其操作中修改occurs來進行計數並返回給調用者。
  • 因爲c通常情況下會傳入一個字面值,並且由於c僅僅是一個char類型,所以通過傳值方式調用更方便快捷。
  • 在這個函數中不會發生特殊情況,但是如果不加const限制,則有可能會在函數中修改s變量。
  • 會導致函數不能正常修改occurs,導致錯誤。

練習 6.16 下面的這個函數雖然合法,但是不算特別有用。指出它的侷限性並設法改善。

bool is_empty(string& s) { return s.empty(); }

侷限性在於常量字符串字符串字面值無法作爲它的實參

可以改爲:

bool is_empty(const tring &s){return s.empty();}

練習 6.17 編寫一個函數,判斷string對象中是否含有大寫字母。編寫另一個函數,把string對象全部改寫成小寫形式。在這兩個函數中你使用的形參類型相同嗎?爲什麼?

#include<iostream>
#include<string>
#include<cctype>
using namespace std;

bool haveupper(const string &s) {
	bool flag = false;
	for (auto c : s) {
		if (isupper(c)) {
			flag = true;
			break;
		}
	}
	return flag;
}

void beclower(string &s) {
	bool flag = false;
	for (auto &c : s) {
		c = tolower(c);
	}
}
int main()
{
	string a = "ABCDaaaa";
	cout << a << endl;
	cout << haveupper(a) << endl;
	beclower(a);
	cout << a << endl;
	cout << haveupper(a) << endl;

	return 0;
}

不同,因爲函數的需求不同,第一個函數只需要訪問字符串s即可,所以用const引用類型,而第二個函數需要訪問並修改字符串s,所以用普通引用類型。

練習 6.18 爲下面的函數編寫函數聲明,從給定的名字中推測函數具備的功能。

  • (a) 名爲 compare 的函數,返回布爾值,兩個參數都是 matrix 類的引用。
  • (b) 名爲 change_val 的函數,返回vector的迭代器,有兩個參數:一個是int,另一個是vector的迭代器。
bool compare(matrix &a, matrix &b);
vector<int>::iterator change_val(int x, vector<int>::iterator iter)

練習 6.19 假定有如下聲明,判斷哪個調用合法、哪個調用不合法。對於不合法的函數調用,說明原因。

double calc(double);
int count(const string &, char);
int sum(vector<int>::iterator, vector<int>::iterator, int);
vector<int> vec(10);
(a) calc(23.4, 55.1);
(b) count("abcda",'a');
(c) calc(66);
(d) sum(vec.begin(), vec.end(), 3.8);

(a)不合法,calc只有一個參數,調用時卻傳入了兩個值。

(b)合法

©合法

(d)合法

練習 6.20 引用形參什麼時候應該是常量引用?如果形參應該是常量引用,而我們將其設爲了普通引用,會發生什麼情況?

當只需要訪問實參的值,而不需要更改實參時,一個用常量引用。

可能會導致本應該合法的調用不合法。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章