C++ Primer笔记3---chapter3易错点

Posted Ston.V

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++ Primer笔记3---chapter3易错点相关的知识,希望对你有一定的参考价值。

1.头文件不应该包含using声明

2.拷贝初始化和直接初始化:对于有连续多少个重复字符的用直接初始化

string s1="hello";    //拷贝初始化
string s2("hello");   //直接初始化
string s3(10,'c');    //直接初始化

 3.string.size()返回的时string::size_type类型的值,可以用auto或者decltype获得其类型(事实上,返回的是一个unsigned int,注意避免和int混用造成由于越界导致的问题)

4.当string的加运算中,有string对象和字符字面值和字符串字面值混在一起时,注意确保每个+号两侧的对象中至少有一个是string

string s1="hello";
string s2=s1 + "world" + "!";    //错误
string s2=(s1 + "world") + "!";  //正确

5.使用基于范围的for循环,若想要改变原数据的内容,不要忘记加引用符号;基于范围的for循环不能改变所遍历序列的大小,因此不能用于向vector中添加元素

    string s="hello world";
    for(auto &c:s)
        c=toupper(c);
    cout<<s<<endl;

6.vector的几种初始化:等号赋值,圆括号(用于构造,指明有几个元素,初始值是啥),花括号(用于指定元素的初始值)

vector<T>v1;

vector<T>v2(v1);

vector<T>v3=(n,val);      //有n个元素,初始值均为val

vector<T>v4(n);           //v4内有n个重复执行初始化了的值(我的编译器里:若为int类型,则有n个0)

vector<T>v5{a,b,c...};    //使用列表初始化,必须要用花括号,不能用圆括号

vector<T>v6={a,b,c...};

但是对于如下,花括号也可以用于构造(当花括号内的值与元素类型相同时为指定元素的具体值,不相同时表示用于构造)

vector<string> v7{10}    //v7有10个默认初始化的string元素

vector<string> v8{10,"ji"}    //v8有10个默认初始化为"ji"的元素

7.若vector和strinng是常量时,要用迭代器只能够使用const_iterator来访问,不可修改;对于普通变量使用iterator和const_iterator均可

vector<int>::const_iterator it3;
string::const_iterator it4;

8.如果对象只需要读操作二不需要写操作,迭代器访问最好使用cbegin()和cend()

vector<int> v;
vector<int> cv;

auto it1=v.begin();    //it1的类型为vector<int>::iterator
auto it2=cv.begin();    //it2的类型为vector<int>::const_iterator

auto it3=v.cbegin();    //it3的类型为vector<int>::const_iterator,若只想读,最好用此

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

10.字符数组或自动加上一个空字符,数组不允许直接拷贝,但是vector可以直接拷贝

char a1[]={'c','+','+'};    //维度是3,但是strlen他的结果是未定义
char a2[]="c++";            //维度是4

char a3[]=a1;    //错误,不允许使用数组初始化另一个数组
a3=a1;           //错误,不能把一个数组直接赋值给另一个数组,注意这里别把a3当做一整形个指针,在上一行定义处没指定维数就会报错

11.数组指针和指针数组(从内到外读

int *ptrs[10];    //ptrs是含有十个整形指针的数组

int &refs[10];    //错误:不存在引用的数组,引用不是对象

int (*Parray)[10];    //Parray是数组指针,该数组含有十个整数

int (&arrRef)[10];    //arrRef是数组引用,该数组含有十个整数

int *(&arry)[10];     //arry是数组的引用,该数组含有10个整形指针

12.对于数组的迭代器就是指针,可用通过begin()和end()函数来获取数组的头尾(注意不是成员函数),事实上,这样我们也就理解了为什么指针和字面值相加,两个指针相减得到的是元素个数的间距,而非真正的地址偏移(指针看做迭代器)

话外:如果p为空指针,允许给他加上或减去一个值为0的整形常量表达式,两个空指针也允许彼此相减,结果为0

int *pbeg=begin(arr);
int *pend=end(arr);
//找到第一个负元素
while(pbeg!=pend && *pbeg>=0)
    pbeg++;

13.标准类型库string,vector也能够执行下标运算,但是其下标必须是无符号类型,而数组的内置下标无此要求,可以为负数

int *p=&a[2];
int k=p[-1];    //k的值为a[1]

14.string与字符数组,vector与C数组的转化

//字符数组和string
string s("hello world");
const char *str=s.c_str();


//数组和vector
int arr[]={1,2,3,4};
vector<int> vec(begin(arr),end(arr));    //vec中的内容是数组arr的拷贝
vector<int> vec1(arr+1,arr+4);           //将指针看成迭代器,vec1内容为{2,3,4}

15.要使用范围for循环处理多维数组,出了最内层的数组,其他所有循环的控制变量都必须是引用类型(干脆都加上得了),否则编译器会将数组转化为整形指针,进而导致编译错误

int main(){
    int a[][3]={{0,1,2},
                {1,2,3},
                {2,3,4}};

    //使用基于范围for循环
    for(auto &row:a){
        for(auto col:row){
            cout<<col;
        }
        cout<<endl;
    }
    
    //使用指针访问,使用a,a+3这样形式也可以,但是用begin(),end()更简洁
    for(auto p=begin(a);p!=end(a);p++){
        for(auto q=(*p);q!=end(*p);q++)
            cout<<*q;
        cout<<endl;
    }
    return 0;
}

16.两个迭代器相减,得到的类型是difference_type

以上是关于C++ Primer笔记3---chapter3易错点的主要内容,如果未能解决你的问题,请参考以下文章

C++ Primer笔记16---chapter13 代码实例

C++ Primer笔记16---chapter13 代码实例

C++ Primer笔记15---chapter13 拷贝控制2

C++ Primer笔记15---chapter13 拷贝控制2

C++ C++ Primer 基础知识笔记

C++ Primer Plus读书笔记