The type unsigned int may be abbreviated as unsigned
Type Conversions
out-of-range assignment
If we assign an out-of-range value to an object of unsigned type, the result is the remainder of the value modulo the number of values the target type can hold.
关于modulo怎么算,看之前的一篇文章。
If we assign an out-of-range value to an object of signed type, the result is undefined.
literal
整数literal
默认类型(比我想的复杂):
decimal literals are signed
decimal literal has the smallest type of int, long, or long long (i.e., the first type in this list) in which the literal’s value fits
octal and hexadecimal literals can be either signed or unsigned types
Octal and hexadecimal literals have the smallest type of int, unsigned int, long, unsigned long, long long, or unsigned long long in which the literal’s value fits
两个字符串literal,中间用 空格、tab、换行 隔开的话,会被连接成单个字符串literal
"a really, really long string literal "
“that spans two lines”
效果等于
“a really, really long string literal that spans two lines”
Variables
C++ Primer 对于 object 的定义是:
An object is a region of memory that has a type. We will freely use the term object regardless of whether the object has built-in or class type, is named or unnamed, or can be read or written.
Initializer(初始值)
initialization and assignment are different operations in C++
C++里变量初始化和赋值是不同的操作
Initialization is not assignment. Initialization happens when a variable is given a value when it is created. Assignment obliterates an object’s current value and replaces that value with a new one.
// C++ primer EN p43 int units_sold = 0; int units_sold = {0}; int units_sold{0}; intunits_sold(0);
Variable Declarations vs Definitions
Declaration:makes a name known to the program, also specifying the type
Definition: in addition to declaration, creates an entity associated with a name - allocates storage and may provide the variable with an initial value
voidfunc(){ externdouble pi = 3.1416; // compile error }
Conventions for Variable Names
原来C++里面有一类名字是C++ Alternative Operator Names,可以像python一样用and,or,not等等表示布尔运算。这些alternative operator是给一些没有&、|这种符号的编码集用的。(很少见,之前根本不知道)
Compound Types
declaration更广泛的定义:
More generally, a declaration is a base type followed by a list of declarators. Each declarator names a variable and gives the variable a type that is related to the base type.
例:
1 2 3 4 5 6 7
int i3 = 1024, &ri = i3; // i3 is an int; ri is a reference bound to i3 // int是base type,i3和&ri是declarator。 // &ri这个declarator给了变量名:ri,和type:int&
double dp, *dp2; // dp2 is a pointer to double; dp is a double // double是base type,dp和*dp2是declarator。 // *dp2这个declarator给了变量名:dp2,和type:int*
// C++ primer 英文版p58 int i = 42; int *p; // p is a pointer to int int *&r = p; // r is a reference to the pointer p r = &i; // r refers to a pointer; assigning &i to r makes p point to i *r = 0; // dereferencing r yields i, the object to which p points; changes i to 0
(不会真有人喜欢写这种代码吧,什么情况下会写成这样……
const Qualifier
const object必须给初始值(被初始化)。
1 2 3 4
// C++ primer EN p59 constint i = get_size(); // ok: initialized at run time constint j = 42; // ok: initialized at compile time constint k; // error: k is uninitialized const
const Objects Are Local to a File
the compiler will usually replace uses of the variable with its corresponding value during compilation
To share a const object among multiple files, you must define the variable as extern.
// C++ primer EN p60 // file_1.cc defines and initializes a const that is accessible to other files externconstint bufSize = fcn(); // file_1.h externconstint bufSize; // same bufSize as defined in file_1.cc
其实不引用file_1.h,直接在cpp文件里用extern const int bufSize;也是一样的效果,但是就会造成相同的代码复制到多个地方,以后如果要改就容易出错。
Reference to const
reference的类型和它绑定的object的类型需要匹配,但是有两个例外,这里是第一个例外:reference to const,可以用literal、表达式和nonconst object初始化,还能用可以转换成reference的类型的其他表达式初始化
we can initialize a reference to const from any expression that can be converted (§ 2.1.2, p. 35) to the type of the reference. In particular, we can bind a reference to const to a nonconst object, a literal, or a more general expression
1 2 3 4 5 6 7 8 9
int i = 42; constint &r1 = i; // we can bind a const int& to a plain int object constint &r2 = 42; // ok: r1 is a reference to const constint &r3 = r1 * 2; // ok: r3 is a reference to const int &r4 = r * 2; // error: r4 is a plain, nonconst reference
double dval = 3.14; constint &ri = dval; // OK, convert from double to int constint &ri2 = 3.14; // OK, convert from double to int
Reference to const可以绑定nonconst的object,但是不能更改object的值。
Pointers and const
pointer to const
pointer的类型需要和它指向的object的类型匹配,但有两个例外,这里是第一个。
我们可以用一个pointer to const指向一个nonconst object
1 2 3
// C++ primer EN p62 double dval = 3.14; // dval is a double; its value can be changed constdouble *cptr = &dval; // ok: but can’t change dval through cptr
// C++ primer EN p63 int errNumb = 0; int *const curErr = &errNumb; // curErr will always point to errNumb constdouble pi = 3.14159; constdouble *const pip = π // pip is a const pointer to a const object
Top-Level const
这个概念之前根本没接触过。
top-level const indicates that an object itself is const. Top-level const can appear in any object type, i.e., one of the built-in arithmetic types, a class type, or a pointer type. Low-level const appears in the base type of compound types such as pointers or references.
1 2 3 4 5 6 7
// C++ primer EN p64 int i = 0; int *const p1 = &i; // we can’t change the value of p1; const is top-level constint ci = 42; // we cannot change ci; const is top-level constint *p2 = &ci; // we can change p2; const is low-level constint *const p3 = p2; // right-most const is top-level, left-most is not constint &r = ci; // const in reference types is always low-level
an expression whose value cannot change and that can be evaluated at compile time.
A literal is a constant expression
A const object that is initialized from a constant expression is also a constant expression
1 2 3 4
constint max_files = 20; // max_files is a constant expression constint limit = max_files + 1; // limit is a constant expression int staff_size = 27; // staff_size is not a constant expression constint sz = get_size(); // sz is not a constant expression
// C++ primer EN p67-68 // Two ways // 1. typedef typedefdouble wages; // wages is a synonym for double typedef wages base, *p; // base is a synonym for double, p for double* // 2. using using SI = Sales_item; // SI is a synonym for Sales_item
wages hourly, weekly; // same as double hourly, weekly; SI item; // same as Sales_item item
Pointers, const, and Type Aliases
1 2 3 4 5
typedefchar *pstring; const pstring cstr = 0; // cstr is a constant pointer to char const pstring *ps; // ps is a pointer to a constant pointer to char
a const that appears in the base type modifies the given type.
When we use pstring in a declaration, the base type of the declaration is a pointer type.
base type到底是什么?在chapter summary里给了定义:
type specifier, possibly qualified by const, that precedes the declarators in a declaration. The base type provides the common type on which the declarators in a declaration can build.
The auto Type Specifier
使用auto创建变量必须有初始值。
1 2
// the type of item is deduced from the type of the result of adding val1 and val2 auto item = val1 + val2; // item initialized to the result of val1 + val2
constint ci = i, &cr = ci; auto b = ci; // b is an int (top-level const in ci is dropped) auto c = cr; // c is an int (cr is an alias for ci whose const is top-level) auto d = &i; // d is an int* (& of an int object is int*) auto e = &ci; // e is const int* (& of a const object is low-level const)
如果要得到top level const,需要显式声明const auto。
1
constauto f = ci; // deduced type of ci is int; f has type const int
auto &g = ci; // g is a const int& that is bound to ci auto &h = 42; // error: we can’t bind a plain reference to a literal constauto &j = 42; // ok: we can bind a const reference to a literal
auto and pointer declarator
在下面这种情况下加不加*效果是一样的
1 2 3
auto i = 0; auto *p = &i; // p is a pointer to int auto d = &i; // d is also a pointer to int
// C++ Primer EN p71 constint ci = 0, &cj = ci; // cj is a reference to const int decltype(ci) x = 0; // x has type const int decltype(cj) y = x; // y has type const int& and is bound to x decltype(cj) z; // error: z is a reference and must be initialized
decltype and References
Generally speaking, decltype returns a reference type for expressions that yield objects that can stand on the left-hand side of the assignment
// EN p71 // decltype of an expression can be a reference type int i = 42, *p = &i, &r = i; decltype(r + 0) b; // ok: addition yields an int; b is an (uninitialized) int decltype(*p) c; // error: c is int& and must be initialized
如果在variable周围加上括号,那decltype得到的类型一定是reference。
1 2 3 4
// EN p71 // decltype of a parenthesized variable is always a reference decltype((i)) d; // error: d is int& and must be initialized decltype(i) e; // ok: e is an (uninitialized) int
Defining Our Own Data Structures
Best Practices:
Headers should have guards, even if they aren’t (yet) included by another header.
所有的头文件都应该用guard。
1 2 3 4 5 6 7 8 9 10
// C++ primer EN p77 #ifndef SALES_DATA_H #define SALES_DATA_H #include<string> structSales_data { std::string bookNo; unsigned units_sold = 0; double revenue = 0.0; }; #endif