Hi!这里是山幺幺的c++ primer系列。写这个系列的初衷是,虽然在学校学习了c++,但总觉得对这门语言了解不深,因此我想来啃啃著名的c++ primer,并在这里同步记录我的学习笔记。由于我啃的是英文版,所以笔记是中英文夹杂的那种。另外由于已有一定的编程基础,所以这个系列不会含有太基础的知识,想入门的朋友最好自己啃书嘻嘻~
简单语句
expression statement
- 表达式后加上分号即变为了expression statement
- Expression statements cause the expression to be evaluated and its result discarded
null statement
; // null statement
Compound Statements (Blocks)
- a block is a scope: Names introduced inside a block are accessible only in that block and in blocks nested inside that block
条件语句
if
switch
- switch括号中的值会转换为integral value
- 可以通过break语句跳出switch
- case labels must be integral constant expressions
- 如果没有break语句,会从第一个case开始continues across all the remaining cases
- 多个case共用一个操作:
switch (ch) {
// any occurrence of a, e, i, o, or u increments vowelCnt
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
++vowelCnt;
break;
}
- 常见bug
switch (ch) {
case 'a':
++aCnt; // oops: should have a break statement
case 'e':
++eCnt; // oops: should have a break statement
case 'i':
++iCnt; // oops: should have a break statement
case 'o':
++oCnt; // oops: should have a break statement
case 'u':
++uCnt;
}
PS:ch = 'e'时,实际发生的是:Execution jumps to the code following the case 'e' label, which increments eCnt. Execution continues across the case labels, incrementing iCnt, oCnt, and uCnt as well.
- default:switch括号中的值不匹配任一case时,跳到default处
switch (ch) {
case 'a': case 'e': case 'i': case 'o': case 'u':
++vowelCnt;
break;
default:
++otherCnt;
break;
}
PS:若写了default case却没有需要做的,那么the default label must be followed by a null statement or an empty block
- case中若要定义变量,最好加上花括号,保证该变量只对该case可见
case true:
// this switch statement is illegal because these initializations might be bypassed
string file_name; // error: control bypasses an implicitly initialized variable
int ival = 0; // error: control bypasses an explicitly initialized variable
int jval; // ok: because jval is not initialized
break;
case false:
// ok: jval is in scope but is uninitialized
jval = next_num(); // ok: assign a value to jval
if (file_name.empty()) // file_name is in scope but wasn't initialized
// ...
// 应该改成
case true:
{
// ok: declaration statement within a statement block
string file_name = get_file_name();
// ...
}
循环语句
while
for
- traditional for和range for
for (auto &r : v)
r *= 2;
// 等价于
for (auto beg = v.begin(), end = v.end(); beg != end; ++beg)
{
auto &r = *beg;
r *= 2;
}
- 不能用range for来add elements to a vector (or other container):在range for中,the value of end() is cached. If we add elements to (or remove them from) the sequence, the value of end might be invalidated
跳转语句
return
第六章会讲
break
- 结束the nearest enclosing while, do while, for, or switch
continue
- 只出现在for, while, or do while中,影响the nearest enclosing loop
goto
- labeled statement
end: return; // end是label
- goto语句的语法:goto label;
- Label identifiers are independent of names used for variables and other identifiers. Hence, a label may have the same identifier as another entity in the program.
- goto语句和对应的label语句必须在同一方程中
- goto cannot transfer control from a point where an initialized variable is out of scope to a point where that variable is in scope
goto end;
int ix = 10; // error: goto bypasses an initialized variable definition
end:
// error: code here could use ix but the goto bypassed its declaration
ix = 42;
- Jumping back to a point before a variable is defined destroys the variable and constructs it again
begin:
int sz = get_size();
if (sz <= 0) {
goto begin;
}
try
Exception Handling
程序的一部分作为detecting part,若这部分无法continue,就认为检测到了错误,交给另一部分代码即handling part处理
-
包含:
- throw expressions:a throw raises an exception,detecting part用throw来表示它检测到了错误
- try blocks:其中有很多catch clauses(即exception handlers),在try block中执行的代码throw出的exception会交由其中一个catch clause来处理
- exception classes:在throw和对应的catch之间传递信息
throw expression
- Throwing an exception terminates the current function and transfers control to a handler that will know how to handle this error.
if (item1.isbn() != item2.isbn())
throw runtime_error("Data must refer to same ISBN");
// if we're still here, the ISBNs are the same
cout << item1 + item2 << endl;
PS:runtime_error is one of the standard library exception types,定义在头文件stdexcept中
try block
- 一般格式
try {
program-statements
} catch (exception-declaration) {
handler-statements
} catch (exception-declaration) {
handler-statements
}
- 当一个catch被选中处理一个exception时,对应的catch clause被执行。catch clause执行结束后,从最后一个catch clause后面紧跟的语句开始执行
- try block对catch是不可见的
- 栗子
while (cin >> item1 >> item2) {
try {
// execute code that will add the two Sales_items
// if the addition fails, the code throws a runtime_error exception
} catch (runtime_error err) {
cout << err.what() << "Try Again? Enter y or n" << endl;
char c;
cin >> c;
if (!cin || c == 'n') {
break; // break out of the while loop
}
}
}
PS:若是上上上段代码throw exception,则会打印Data must refer to same ISBN Try Again? Enter y or n
- 含有try block的函数调用另一个含有try block的函数并抛出异常时,查找catch clause的顺序是:The search for a handler reverses the call chain. When an exception is thrown, the function that threw the exception is searched first. If no matching catch is found, that function terminates. The function that called the one that threw is searched next. If no handler is found, that function also exits. That function’s caller is searched next, and so on back up the execution path until a catch of an appropriate type is found.
- 如果没找到对应类型的catch clause,或者程序遇到异常却不在try block中,那么execution is transferred to a library function named terminate. The behavior of that function is system dependent but is guaranteed to stop further execution of the program.
exception的类型
- 头文件exception:定义了exception类型,It communicates only that an exception occurred but provides no additional information.
- 头文件stdexcept:
- 头文件new:定义了bad_alloc类型
- 头文件type_info:定义了bad_cast类型
各exception类型支持的操作
- We can create, copy, and assign objects of any of the exception types.
- exception, bad_alloc, and bad_cast objects只能default initialize;其他类型不能default initialize,只能且必须用string初始化
- what():返回const char*;what返回的内容取决于exception的类型。For the types that take a string initializer, the what function returns that string. For the other types, the value of the string that what returns varies by compiler.