Eff C++ 笔记1

 • C++是一个语言联邦(Federation of languages)函数

1. C Style languagethis

2. Object-Oriented C++spa

3. Template C++指针

4. STL/TR1/boost..代码规范

 

 • 使用const,enum,inline代替#definecode

1.  使用const datatype constName = constValue 代替 #define constName constValue对象

  好比全局常量:blog

const int maxN = 1000005; //代替 #define maxN 1000005

  在类中,类专属常量:编译器

class someClass{
private:
    static const int maxN = 1000005;
    int someData[maxN];
    ...
}

 

2. enum hack!string

class someClass{
private:
    enum { maxN = 1000005 };//enum令maxN变成一个记号名称
    int someData[maxN];
    ...
}

  enum的某些特性更像#define而不是const,某些状况下更符合咱们的需求。(例如取地址对于enum不合法而对const就合法

  enum hack使template metaproprogramming的基础技术。

 

3. 使用inline function代替宏

  常见宏 #define call_with_max(a, b) foo(a > b ? a : b) 会出现大量的错误,

必须使用小括号将参数所有区别 #define call_with_max(a, b) foo((a) > (b) ? (a) : (b)) ,

即使如此在实际操做时依旧容易出错(不能扩展代码与灵活调用),应用inline function取代

template <typename T>
inline void callWithMax(const T& a, const T& b){
    foo(a > b ? a : b);
}

 

 

 • Const的妙用

1. Const声明帮助编译器侦测出错误

  const指定了一个不可改动的对象,而编译器会强制的实施它。(!指出来能够得到编译器的帮助,确保其不被违反!)

这个对象能够是global或者namespace域中的常量。也能够修饰block scope中被声明为static的对象,亦能够修饰class内部的全部变量。

而对于指针,能够指出指针自身指针所指二者皆是,或二者皆不是Const。在*左表示指针所指是常量,在*右表示指针自身是常量,而在*两侧表示二者皆是常量。

int someValue = 12345;
int* pSomeValue = someValue;        // 二者皆不是常量
const int* pSomeValue = someValue     // 所指为常量
int* const pSomeValue = someValue     // 指针为常量
const int* const pSomeValue = someValue // 二者皆是常量
void foo(const dataType* arg) // 传入一个指向常量的指针
void foo(dataType const* arg) // 与上面相同 在*左次序颠倒没有区别

迭代器也是指针衍生出来的,因此

std::vector<int> vec;
...
const std::vector<int>::iterator iter = vec.begin(); // 迭代器的做用就像一个 T* const (模板变量的常量指针)
*iter = 12345; // ok! 指针所指不是常量
++iter;     // error! 指针自己是常量

std::vector<int>::const_iterator cIter = vec.begin(); // cIter的做用如同一个 const T* (模板常量的变量指针)
*cIter = 12345; // error! 指针所指是常量
++cIter;     // ok! 指针自己不是常量

  

  将const应用于函数声明

良定义的数据类型应尽可能避免隐式类型转换,这时返回一个常量值就十分有用

class Rational {...};
const Rational operator+ (const Rational& lhs, const Rational rhs);
const Rational operator* (const Rational& lhs, const Rational rhs);
...

这样定义, if(a * b = c) // 本意是想作一个if(a * b == c)的比较 这样的错误就不会出现,而会被编译器直接警告。

 

2. const成员函数

使用const来控制成员函数对对象的可读写性是很重要的,由于这样可使class借口更容易被理解,而且还可使操做const对象成为可能。这对高效编写代码很重要。

class SomeText {
public:
    ...
    const char& operator[](std::size_t position) const
    { return text[position]; }
    char& operator[](std::size_t position)
    { return text[position]; }
}

SomeText text("Hello,world!");
std::cout << text[0]; // 调用non-const方法 能够读
text[0] = 'A';        // 调用non-const方法 能够写
const SomeText cText("Hello,world!");
std::cout << cText[0]; // 调用const方法 能够读
cText[0] = 'A';        // 调用const方法 不可写!

对于在const中也想改变的量,使用mutable能够声明在const成员函数内依旧可被更改的变量。

若是成员函数代码功能相同而只有常量变量的区别,能够const_cast,static_cast来避免代码重复。

class SomeText {
public:
    ...
    const char& operator[](std::size_t position) const
    {
        ...
        ...
        ...
        return text[position];
    }
    char& operator[](std::size_t position) {
        return const_cast<char&>         // 移除返回值的const
                (static_cast<const SomeText&> // 为*this加上const
                    (*this)[position]);     // 调用const op[]
    }

 

 • 变量与对象的初始化与代码规范

1. 代码规范:

 类型  规范  示例
简单数据类型  首字母小写表示类型,以后按单词分割每单词首字母大写。
int iMaxNum = 10000;
char cRank = 'A';
string sName = "LevisonChen";
double dSpeed = 1.357;
int* pMaxNum = iMaxNum;
复杂数据类型  首字母小写,首词表示数据类型,以后按单词分割每单词首字母大写
std::vector<int> vecEdges;
函数 按单词分割每单词首字母大写
void Foo(){ ... }
int GetMaxinum(std::vector<int> vecArg){ ... }
类与结构体 按单词分割每单词首字母大写,私有字段不使用首词表示数据类型
class SomeClass { ... }
struct SomeStruct { ... }
 缩进 tab-4spaces缩进 
{
    ...
    {
        ...
        {
            ...
            ...
            ...
        }
        ...
    }
    ...
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2. 不要混淆赋值(assignment)和初始化(initialization)

class Person {
public:
    Person(const std::string& sName,
           const std::int& iAge,
           const std::list<PhoneNumber>& listPhones,
           const std::list<EmailAddress>& listEmails);
private:
    std::string name;
    std::int age;
    std::list<PhoneNumber> phones;
    std::list<EmailAddress> emails;
};

Person::Person(const std::string& sName,
               const std::int& iAge,
               const std::list<PhoneNumber>& listPhones,
               const std::list<EmailAddress>& listEmails)
{
    name = sName;    
    age = iAge;
    phones = listPhones;
    emails = listEmails;
} // 这是赋值而非初始化!
Person::Person(const std::string& sName,
               const std::int& iAge,
               const std::list<PhoneNumber>& listPhones,
               const std::list<EmailAddress>& listEmails)
   :name(sName),    
    age(iAge),
    phones(listPhones),
    emails(listEmails)    // 这是初始化!
{} 

为了消除跨编译时的单元初始化次序问题,应以local static对象替换non-local static对象。

相关文章
相关标签/搜索