C++ Primer 学习笔记之 --- 学习总结

Best Practices


  1. 出于与变量初始化相同的原因,对动态分配的对象进行初始化通常是个好主意(12.1.2)
  2. 坚持只使用智能指针,就可以避免所有这些问题。对于一块内存,只有在没有任何智能指针指向它的情况下,智能指针才会自动释放它。(12.1.2)
  3. 通常情况下,不应该重载逗号、取地址、逻辑与和逻辑或运算符
  4. 通常,输出运算符应该主要负责打印对象的内容而非控制格式,输出运算符不应该打印换行符(14.2.1)
  5. 当读取操作发生错误时,输入运算符应该负责从错误中恢复(14.2.2)
  6. 如果某个类在逻辑上有相等性的含义,则该类应该定义operator==,这样做可以使得用户更容易使用标准库算法来处理这个类(14.3.1)
  7. 如果存在唯一一种逻辑可靠的<定义,则应该考虑为这个类定义<运算符。如果类同时还包括==,则当且仅当<的定义和==产生的结果一致时才定义<运算符。(14.3.2)
  8. 赋值运算符必须定义为类的成员,复合赋值运算符通常情况下也应该这样做。这两类运算符都应该返回左侧运算对象的引用(14.4)
  9. 如果一个类包含下标运算符,则它通常会定义两个版本:一个返回普通引用,另一个是类的常量并且返回常量引用。(14.5)
  10. 定义递增和递减运算符的类应该同时定义前置版本和后置版本。这些运算符通常应该被定义成类的成员(14.6)、
  11. 为了与内置版本保持一致,前置运算符应该返回递增或递减后对象的引用。(14.6)
  12. 为了内置版本保持一致,后置运算符应该返回对象的原值(递增或递减之前的值),返回的形式是一个值而非引用。(14.6)

NOTE


  1. 如果你将shared_ptr存放于一个容器中,而后不再需要全部元素,而只使用其中一部分,要记得用erase删除不再需要的那些元素。(12.1.1)
  2. 到底是用一个计数器还是其他数据结构来记录有多少指针共享对象,完全由标准库的具体实现来决定。关键是智能指针类能记录多少个shared_ptr指向相同的对象,并能在恰当的时候自动释放对象。(12.1.1)
  3. 使用动态内存的一个常见原因是允许多个对象共享相同的状态。(12.1.1)
  4. 我们可以重载赋值运算符。不论形参的类型是什么,赋值运算符都必须定义为成员函数(14.4)
  5. 下标运算符必须是成员函数(14.5)
  6. 因为我们不会用到int形参,所以无须为其命名(14.6)
  7. 箭头运算符必须是类的成员,解引用运算符通常也是类的成员,尽管并非必须如此。(14.7)
  8. 重载的箭头运算符必须返回类的指针或者自定义了箭头运算符的某个类的对象。(14.7)



TIPS



WARNING


  1. 虽然使用动态内存是必要的,但正解的管理动态内存是棘手的(12)
  2. 在学习第13章之前,除非使用智能指针来管理内存,否则不要分配动态内存(12.1.2)
  3. 由内置指针(而不是智能指针)管理的动态内存在被显式释放前一直都会存在(12.1.2)
  4. 使用一个内置指针来访问一个智能指针所负责的对象是很危险的,因为我们无法知道对象何时会被销毁(12.1.3)
  5. get用来装将指针的访问权限传递给代码,你只有在确定代码不会delete指针的情况下,才能使用get。特别是,永远不要用get初始化另一个智能指针或者为另一个智能指针赋值(12.1.3)

问题汇总


#

vector v1(10); //v1 有10个元素,每个值为0

vector v2{10}; //v2 有1个元素,每个值为10

vector v3(10,1); //v1 有10个元素,每个值为1

vector v4{10,1}; //v2 有2个元素,分别为10,1


#

int i = 1,&ci = i;

decltype(ci) z;//错误:z是一个引用,必须初始化

decltype((i)) z;//错误:注意括号()


#

int arr[10] //arr 是一个含有10个整数的数组

int *p1[10] //p1是一个含有10个指针的数据

int (*p2)[10] = &arr; //p2是一个指针,它指向含有10个整数的数组


#用struct和class定义类的唯一区别是默认的访问权限


#友元

extern std::ostream& storeOn(std::ostream &,Screen &);

extern BitMap& storeOn(BitMap &, Screen &);

class Screen {

// storeOn的ostream版本能访问Screen对象的私有化部分

friend std::ostream& storeOn(std::ostream &,Screen &);

};


#构造函数初始值列表

class ConstRef {

public:

        ConstRef(int ii);

private:

        int i;

        const int ci;

        int &ri;

};

//错误的初始化

CostRef::ConstRef(int ii)

{

       i = ii;

       ci = ii;//错误

       ri = i;//错误

}

//正确:显式地初始化引用和const成员

CostRef::ConstRef(int ii):i(ii),ci(ii),ri(i){}


#默认构造函数

class NoDefault {

public:

       NoDefault(const std::string&);

};


struct A{

        NoDefault my_mem;

};

A a;//错误:不能为A 合成构造函数

struct B {

B() {}//错误

NoDefault b_member;

}


#不完全类型:

class A{

private:

static A sa;

A *pa;

        A a;//错误,不能是不完全类型

};


#虚函数:动态绑定只能通过调用指针或引用的时候才发生,普通类型则直接确定

base = derived;         //把derived的Quote部分拷贝给base

base.net_price(20)    //调用Quote::net_price

#派生类的成员和友元只能访问派生类对象中的基类部分的受保护成员对于普通的基类对象中的成员不具有特殊的访问权限


#聚合类:只含有公有成员的类,并且没有类内初始值或构造函数。聚合类的成员可以使用花括号括起来的初始值列表进行初始化

#委托构造


#explicit 概念

你可能感兴趣的:(C++)