C++ Primer 读书笔记1

1、在Windows系统中输入文件结束符的方法为Ctrl+Z

2、如何选择类型?

1) Use an unsigned type when youknow that the values cannot be negative

2) Use int for integer arithmetic.short is usually too small and, in practice, long often has the same size asint. If your data values are larger than the minimum guaranteed size of an int,then use long long.

3) Do not use plain char or boolin arithmetic expressions. Use them only to hold characters or truth values.Computations using char are especially problematic because char is signed onsome machines and unsigned on others. If you need a tiny integer, explicitlyspecify
either signed char or unsigned char.

4) Use double for floating-pointcomputations; float usually does not have enough precision, and the cost ofdouble-precision calculations versus single-precision is negligible. In fact,on some machines, double-precision operations are faster than single.
Theprecision offered by long double usually is unnecessary and often entailsconsiderable run-time cost.

signed char c2 = 256;   // assuming 8-bit chars, the value of c2 is undefined

3、If we assign anout-of-range value to an object of signed type, the result is undefined. Theprogram might appear to work, it might crash, or it might produce garbagevalues.

4、Caution: Don’t Mix Signed and Unsigned Types.

5、  ‘a‘  // character literal

"HelloWorld!"  // string literal

The type of a string literal is array of constant chars. Thecompiler appends a null character (’\0’) to every string literal. Thus, theactual size of a string literal is one more than its apparent size. Forexample, the literal ‘A‘ represents the single
character A, whereas the stringliteral "A" represents an array of two characters, the letter A andthe null character.

// multiline string literal
 std::cout << "a really, really long string literal "
<span style="white-space:pre">	</span>      "that spans two lines" << std::endl;

6、When you write a long literal,use the uppercase L; the lowercase letter l is too easily mistaken for thedigit 1.

7、The word nullptr is a pointerliteral.

8、Initialization is notassignment. Initialization happens when a variable is given a value when it iscreated. Assignment obliterates an object’s current value and replaces thatvalue with a new one.

9、The generalized use of curlybraces for initialization was introduced as part of the new standard. This formof initialization previously had been allowed only in more restricted ways,this form of initialization is referred to as list initialization.

When used with variables of built-in type, this form ofinitialization has one important property: The compiler will not let us listinitialize variables of built-in type if the initializer might lead to the lossof information:

long double ld = 3.1415926536;
int a{ld}, b = {ld}; // error: narrowing conversion required
int c(ld), d = ld;   // ok: but value will be truncated

10、We recommend initializing everyobject of built-in type. It is not always necessary, but it is easier and saferto provide an initializer until you can be certain it is safe to omit theinitializer.

11、A declaration makes a name known to the program. A file that wants touse a name defined elsewhere includes a declaration for that name. Adefinition creates the associatedentity.

extern int i;   // declares but does not define i
int j;          // declares and defines j
extern double pi = 3.1416; // definition

It is an error to provide an initializer on an externinside a function.

Note: Variables must be defined exactly once but can be declared manytimes.

12、Warning: It isalmost always a bad idea to define a local variable with the same name as aglobal variable that the function uses or might use.

13、the type of a reference and theobject to which the reference refers must match exactly. Moreover, for reasonswe’ll explore in § 2.4.1, a reference may be bound only to an object, not to aliteral or to the result of a more general expression:

int &refVal4 = 10;   // error: initializer must be an object
double dval = 3.14;
int &refVal5 = dval; // error: initializer must be an int object

14、A pointer is a compound type that “points to” another type. Likereferences, pointers are used forindirect access to other objects. Unlike a reference, a pointer is an object inits own right. Pointers can
be assigned and copied; a single pointer can pointto several different objects over its lifetime. Unlike a reference, a pointerneed not be initialized at the time it is defined. Like other built-in types,pointers defined at block scope have undefined value
if they are notinitialized.

15、There are several ways toobtain a null pointer:

int *p1 = nullptr; // equivalent to int *p1 = 0;
int *p2 = 0;       // directly initializes p2 from the literal constant 0
// must #include cstdlib
int *p3 = NULL;    // equivalent to int *p3 = 0;
ModernC++ programs generally should avoid using NULL and use nullptr instead.

16、A reference is not an object.Hence, we may not have a pointer to a reference. However, because a pointer isan object, we can define a reference to a pointer:

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

The easiest wayto understand the type of r is to read the definition right to left. The symbolclosest to the name of the variable (in this case the & in &r) is theone that has the most immediate effect on the variable’s type. Thus, we knowthat r is a reference.
The rest of the declarator determines the type to whichr refers. The next symbol, * in this case, says that the type r refers to is apointer type. Finally, the base type of the declaration says that r is areference to a pointer to an int.

17、Because we can’t change thevalue of a const object after we create it, it must be initialized. As usual,the initializer may be an arbitrarily complicated expression:

const int i = get_size();  // ok: initialized at run time
const int j = 42;          // ok: initialized at compile time
const int k;               // error: k is uninitialized const

Among theoperations that don’t change the value of an object is initialization— when weuse an object to initialize another object, it doesn’t matter whether either orboth of the objects are consts:

int i = 42;
const int ci = i;    // ok: the value in i is copied into ci
int j = ci;          // ok: the value in ci is copied into j

18

// file_1.cc defines and initializes a const that is accessible to other files
extern const int bufSize = fcn();
// file_1.h
extern const int bufSize; // same bufSize as defined in file_1.cc

Note:To share aconst object among multiple files, you must define the variable as extern.

19、References to const

const int ci = 1024;
const int &r1 = ci;   // ok: both reference and underlying object are const
r1 = 42;              // error: r1 is a reference to const
int &r2 = ci;         // error: non const reference to a const object<strong>
</strong>

we noted thatthere are two exceptions to the rule that the type of a reference must matchthe type of the object to which it refers. The first exception is that we caninitialize 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 areference to const to a nonconst object, a literal, or a more generalexpression:

int i = 42;
const int &r1 = i;      // we can bind a const int& to a plain int object
const int &r2 = 42;     // ok: r1 is a reference to const
const int &r3 = r1 * 2;  // ok: r3 is a reference to const
int &r4 = r1 * 2;        // error: r4 is a plain, non const reference

double dval = 3.14;
const int &ri = dval;
《==》
const int temp = dval;   // create a temporary const int from the double
const int &ri = temp;    // bind ri to that temporary

20、Pointers and const

const double pi = 3.14;   // pi is const; its value may not be changed
double *ptr = π        // error: ptr is a plain pointer
const double *cptr = π // ok: cptr may point to a double that is const
*cptr = 42;               // error: cannot assign to *cptr
double dval = 3.14;       // dval is a double; its value can be changed
cptr = &dval;             // ok: but can't change dval through cptr

21、A constant expression is anexpression 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 aconstant expression is also a constant expression.

const int max_files = 20;    // max_files is a constant expression
const int limit = max_files + 1; // limit is a constant expression
int staff_size = 27;       // staff_size is not a constant expression
const int sz = get_size(); // sz is not a constant expression

Under the new standard, we can ask the compiler to verify that avariable is a constant expression by declaring the variable in a constexprdeclaration. Variables declared as constexpr are implicitly const and must beinitialized by constant expressions:

constexpr int mf = 20;        // 20 is a constant expression
constexpr int limit = mf + 1; // mf + 1 is a constant expression
constexpr int sz = size();    // ok only if size is a constexpr function

Generally, it isa good idea to use constexpr for variables that you intend to use as constantexpressions.

22、A type alias is a name that is a synonym for another type.

We candefine a type alias in one of two ways. Traditionally, we use a typedef:

typedef double wages;  // wages is a synonym for double
typedef wages base, *p; // base is a synonym for double, pfor double*

The new standard introduced a second way to define a typealias, via an alias declaration:

using SI = Sales_item; // SI is a synonym for Sales_item

23、Pointers, const, and Type Aliases

typedef char *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

24

auto i = 0, *p = &i;      // ok: i is int and p is a pointer to int
auto sz = 0, pi = 3.14;   // error: inconsistent types for sz and pi
int i = 0, &r = i; auto a = r;  // a is an int (r is an alias for i, which has type int)
const int 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)
const auto 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
const auto &j = 42; // ok: we can bind a const reference to a literal
auto k = ci, &l = i;    // k is int; l is int&
auto &m = ci, *p = &ci; // m is a const int&;p is a pointer to const int
// error: type deduced from i is int; type deduced from &ci is const int
auto &n = i, *p2 = &ci;

25、etimes we want to define avariable with a type that the compiler deduces from an expression but do notwant to use that expression to initialize the variable. For such cases, the newstandard introduced a second type specifier, decltype, which returns the
typeof its operand. The compiler analyzes the expression to determine its type butdoes not evaluate the expression:

decltype(f()) sum = x; // sum has whatever type f returns

The way decltypehandles top-level const and references differs subtly from the way auto does.When the expression to which we apply decltype is a variable, decltype returnsthe type of that variable, including top-level const and references:

const int ci = 0, &cj = ci;
decltype(ci) x = 0; // x has type const
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

decltypeand References

// 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

// 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

Remember that decltype((variable )) (note,double parentheses) is always a reference type, but decltype( variable ) is areference type only if variable is a reference.

时间: 2024-10-03 22:41:58

C++ Primer 读书笔记1的相关文章

C++primer读书笔记11-多态

多态也是C++中的一个重要的方面,多态和动态类型,虚函数本质上是指相同的事情. 1 虚函数 类中的成员函数原型前面加上virtual 表面这个函数是个虚函数.虚函数的目的是为了在继承它的派生类中重新定义这个函数,以便于通过基类的指针或引用在运行时对派生类的函数进行调用. 2 派生类和虚函数 派生类一般情况下要重定义所继承的虚函数,有几个注意事项. <1>虚函数的声明必须和基类中的函数声明原型完全一致,例外的是当基类返回基类型的指针或者引用的时候,派生类可以派生类类型的指针或者引用 <2&

C++中的volatile(Primer读书笔记)

时间:2014.05.24 地点:基地 -------------------------------------------------------------------------- 一.简述 volatile限定符平时很少用到,今天倒是碰到了,所幸探个明白.volatile 英文字面意思是"不稳定的",确切的计算机含义时与机器相关,所以在对包含volatile的程序在移植到新机器或使用不同的编译器时往往还需要对编译器进行一些改变. -----------------------

C++ primer读书笔记10-继承

封装,继承,多态是C++的三大基本概念,这里着重总结一下继承相关的东西 1 类派生列表 类派生列表指定派生类要继承的基类,派生列表中有一个或者多个基类如: class B : public A1,protected A2,private A3 但是单继承时最常见的,多继承不多见 2 派生类的定义 派生类继承时,会包含父类的所有成员,即便私有成员不能被访问.父类中的虚函数,在派生类中一般也要定义,如 果不定义的话,派生类将继承基类的虚函数 3 基类必须是已经定义的 一个仅仅声明的类,是不能出现在派

C++primer读书笔记9转换与类类型

有时候指定了自己类类型来表示某种类型数据如SmallInt,那么为了方便计算就会指定一个转换操作符,将该类类型在某种情况下自动的转换为指定的类型 <1>转换操作符 operator type(); 转换函数必须是类成员函数,不能指定返回类型,并且形参列表必须为空,并且通常不应该改变转换对象,所以操作符通常定义为const成员. #include <iostream> using namespace std; class SmallInt { public: SmallInt(int

C++ Primer 读书笔记整理(一)

1.读取数量不定的输入数据时可以把cin语句放到条件判断语句中,如果流的状态有效则读取成功,否则读取失败. 例如: while(cin>>value) /* do something */ 2.顶层const与底层const的区别 1)顶层const表示任意的对象是const(即常量) 例如: const int value = 0; // i是顶层const常量 int i= 0; int *const ptr = &i; //ptr是顶层const常量 2)底层const一般用在引

c++ primer读书笔记之c++11(二)

1 新的STL模板类型,std::initializer_list<T> c++11添加了initializer_list模板类型,用于提供参数是同类型情况的可变长度的参数传递机制,头文件是<initializer_list>. 其具体接口可参考cplusplus.com的介绍,地址如下:http://www.cplusplus.com/reference/initializer_list/initializer_list/?kw=initializer_list 与vector不

c++ primer读书笔记之c++11(四)

1  带有作用域的枚举 scoped-enumeration 相信大家都用过枚举量,都是不带有作用域的,在头文件中定义需要特别注意不要出现重名的情况.为了解决这种问题,c++11提供了带作用于的枚举.可以使用class EnumName定义,示例代码如下: enum {ZERO, ONE, TWO}; enum class color {RED, BLUE, GREEN}; 上面的是没有作用域的枚举定义形式,下面是带有作用域的枚举定义形式,调用带有作用域的枚举必须指定作用域,否则会编译出错. 还

c++ primer读书笔记之c++11(三)

1 =default构造函数限定符 c++11针对构造函数提供了=default限定符,可以用于显式指定编译器自动生成特定的构造函数.析构或赋值运算函数.参考代码如下: class CtorDftType { public: CtorDftType()=default; CtorDftType(const CtorDftType&)=default; CtorDftType & operator = (const CtorDftType &)=default; ~CtorDftTy

函数(C++ Primer读书笔记)

C++ Primer 第五版课后题 练习6.32 :下面的函数合法吗?如果合法,说明其功能:如果不合法,修改其中的错误并解释原因. #include <iostream> using namespace std; int &get(int *arry, int index) { return arry[index]; } int main() { int ia[10]; for (int i = 0; i != 10; ++i) get(ia, i) = i; return 0; }

c++ primer读书笔记之c++11(一)

1 新的关键词nullptr c++11引入新的关键词nullptr,用于表示空指针,用于替换之前c提供的NULL(最初NULL是定义在stdlib中的宏定义,通常是0). 2 新的别名定义机制 alias declaration c++提供了使用typedef定义的别名机制,但是有时候很难理解.为了更好的使用别名机制,c++11提供了新的别名定义机制,类似代码如下: // alias declarations using VInt = int; // type alias using PInt