c++ primer 5th 笔记:第三章

第三章:字符串、向量和数组

  笔记

    1. 头文件不应包含using声明,因为可能不经意间包含时,会造成名字冲突

    2. 如果使用等号(=)初始化一个变量,实际上执行的是拷贝初始化(copy initialization)。如果不适用等号,则执行的是直接初始化(direct initialization)。如:

    string s5 = "hiya";  // 拷贝初始化
    string s6("hiya");   // 直接初始化
    string s7(10, 'c');  // 直接初始化,s7的内容是cccccccccc

    3. 在c++11新标准中,允许编译器通过auto或者decltype来推断变量的类型。如:

 

    string line;
    auto len = line.size();    // len的类型是stirng::size_type

    4. 字符串字面值与string是不同的类型。

    5. c++11新标准提供一种语句:范围for(range for)语句。形式是:

    for (declaration : expression)
        statement

    其中,expression部分是一个对象,用于表示一个序列。declaration部分负责定义一个变量,该变量将被用于访问序列中的基础元素。每次迭代,declaration部分的变量会被初始化为expression部分的下一个元素值。例如:

     例一:

    string str("some string");
    for (auto c : str)             // 用str中的每个字符依次去初始化c
        cout << c << endl;    // 输出当前字符,后面紧跟一个换行符

     例二:

    string s("Hello World);
    // 转换成大写形式
    for (auto &c : s)      // 对于s中的每个字符(注意:c是引用)
        c = toupper(c);   // c是一个引用,因此复制语句将改变s中字符的值
    cout << s << endl;

    6. string使用下标运算符([])访问时,返回值是该位置上字符的引用。如:

    string s("some string");
    for (decltype(s.size()) index = 0;         // 类型推断
                    index != s.size() && !isspace(s[index]); ++index) // 注意判断的顺序
        s[index] = toupper(s[index]);  // 将当前字符改写成大写形式

    7. 编译器根据模板创建类或函数的过程称为实例化(instantiation),当使用模板时,需要指出编译器应当把类或函数实例化成何种类型。

    8. c++11新标准提供了一种为vector对象的元素赋初值的方法,即列表初始化

    vector<string> articles = {"a", "an", "the"};

    9. 如果循环体内包含有向vector对象添加元素的语句,则不能使用范围for循环,即范围for语句不应该改变所遍历序列的大小

    10. 要使用size_type,需首先指定它是由哪种类型定义的。如:

    vector<int>::size_type    // 正确
    vector::size_type    // 错误

    11. 不能使用下标形式添加元素,并且使用下标访问元素要确保元素存在,另一种有效手段是尽可能使用范围for语句

    12. c++程序员更习惯在for循环中使用!=,而非<进行判断,所有标准库容器都定义了==和!=,但是它们中的大多数都没有定义<运算符。

    13. begin()和end()返回的具体类型有对象是否是常量决定,常量返回:const_iterator,非常量返回:iterator。此外,c++11新标准引入了两个新函数,分别是cbegin()和cend(),用来返回const_iterator类型。如:

    // 依次输出text的每一行直至遇到一个空白行为止
    for (auto it = text.cbegin();
            it != text.cend() && !it->empty(); ++it)
        cout << *it << endl;

    14. 凡是使用了迭代器的循环体,都不要向迭代器所属的容器添加元素

    15. string和vector都定义了difference_type,因为这个距离可正可负,所以difference_type是带符号类型的。

    16. 数组的维度必须是一个常量表达式,如:

    unsigned cnt = 42;     // 不是常量表达式
    constexpr unsigned sz = 42;  //常量表达式
    int *parr[sz];   //含有42个整型指针的数组
    stirng bad[cnt];   //错误:cnt不是常量表达式

    17. 要理解数组声明的含义,最好的方法是从数组的名字开始按照由内向外的顺序阅读。

    18. 在很多实用数组名字的地方,编译器一般会自动将其替换为一个指向数组首元素的指针。但是,当使用decltype关键字时不会发生转换指针,如定义数组ia[10]后,使用decltype(ia)返回类型是10个元素构成的数组。

    19. c++11新标准引入两个名为begin()和end()的函数,在iterator头文件中定义。如:

    int ia[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    int *beg = begin(ia);    // 指向ia首元素的指针
    int *last = end(ia);      // 指向ia尾元素的下一个位置的指针

    20. 两个指针相减的结果是一种名为ptrdiff_t的标准库类型,和size_t一样,ptrdiff_t也是一种定义在cstddef头文件中的机器相关的类型。

    21. 尽管c++支持c风格字符串,但是c++程序中最好还是不要使用它们。

    22. 使用数组初始化vector对象:

    int int_arr[] = {0, 1, 2, 3, 4, 5};
    vector<int> ivec(begin(int_arr), end(int_arr));

    23. c++中没有多维数组,通常所说的多维数组其实是数组的数组

    24. 要使用范围for语句处理多维数组,除了最内层的循环外,其他所有循环的控制变量都应该是引用类型。这样是为了避免数组被自动转成指针。如:

    for (const auto &row : ia)     // ia为二维数组
        for (auto col : row)
           cout << col << endl;

  术语

    拷贝初始化(copy initialization)、直接初始化(direct initialization)、范围for(range for)语句、容器(container)、

    类模板(class template)、实例化(instantiation)、迭代器(iterator)、C风格字符串(C-style character string)。

 

                                                  2016-10-27

posted @ 2016-10-26 19:59  西伯利亚狼zz  阅读(221)  评论(0编辑  收藏  举报