今日学习札记——C++Primer补充2(11.8)

来源:互联网 发布:少数民族 知乎 编辑:程序博客网 时间:2024/06/05 06:55
1. 空语句( ;),一个单独的分号。如果在程序的某个地方,语法上需要一条语句而逻辑上不要,此时应该使用空语句。
例如: while(cin>>s && s!=sought)
;   //空语句


2. 别漏写分号,也别多写分号
例如:while(iter!=svec.end());  //额外的分号,循环体是那条空语句
       ++iter;
       
3. 当不确定到底要迭代多少次时,使用while循环比较合适。定义在while条件部分或while循环体内的变量每次迭代都经历从创建到销毁的过程。

4. C++11引入了范围for语句,这种语句可以遍历容器或其他序列的所有元素。如果要对序列中的元素执行写操作,循环变量必须声明成引用类型。
例如:vector<int> v = {0,1,2,3,4,5,6,7,8,9};
      for( int &r : v)
        r *= 2;


5. do while语句先执行循环体后检查条件。不管条件的值如何,我们都至少执行一次循环。
   例如:不断提示用户输入一对数,然后求其和
        string rsp;
        do{
        cout<<"please enter two values: ";
        int val1 = 0, val2 =0;
        cin >>val1 >>val2;
        cout <<"The sum of " <<val1<<" and " <<val2 <<" = "<<val1+val2 <<"\n\n"
        <<"More? Enter yes or no: ";
        cin >> rsp;
        }while(!rsp.empty() && rep[0] !='n');
        
6. 带标签的goto语句。
例如:
static int count = 1;
begin:
int v=0; 
count++;
if(count<10)
goto begin;


7. 函数的声明和函数的定义非常相似,唯一的区别是函数声明无须函数体,用一个分号替代即可。我们建议在头文件中声明,在源文件中定义

  (含有函数声明的头文件应该被包含到定义函数的源文件中)



8. 拷贝大的类类型对象或者容器对象比较低效,甚至有的类类型根本就不支持拷贝操作。当某种类型不支持拷贝操作时,函数只能通过引用形参访问该类型的对象。
   如果函数无须改变引用形参的值,最好将其声明为常量引用。
   例如:比较两个string对象的长度。
   bool isShorter(const string &s1, const string &s2)
   {
    return s1.size() <s2.size();
   }
   

9. 数组的两个性质是:不允许拷贝数组以及使用数组时(通常)会将其转换成指针。因为数组会被转换成指针,所以当我们为函数传递一个数组时,实际上传递

    的是指向数组首元素的指针。

例如:一下三种print函数是等价的
void print(const int*);
void print(const int[]);
void print(const int[10]);
- 管理数组实参的第一种方法是要求数组本身包含一个结束标记,例如C风格字符串存储在数组中,并且在最后一个字符后面跟着一个空字符。例如:
void print(const char *cp)
{
if(cp)
while(*cp)
cout <<*cp++;  //输出当前字符并将指针向前移动一个位置
}
- 管理数组实参的第二种方法是传递指向数组首元素和尾后元素的指针。例如:
void print(const int *beg, const int *end)
{ //输出[beg,end)之间的所有元素
while(beg !=end)
cout <<*beg++<<endl;
}
- 管理数组实参的第三种方法是专门定义一个表示数组大小的形参。例如:
void print(const int ia[], size_t size)
{
for(size_t i=0; i!=size; ++i)
cout <<ia[i]<<endl;
}
- 管理数组实参的第四种方法是定义数组的引用。例如:
void print(int (&arr)[10])
{
for(auto elem : arr)
cout<<elem<<endl;
}


10. 传递多维数组。因为我们处理的是数组的数组,所以首元素本身就是一个数组,指针就是一个指向数组的指针。数组第二维(以及后面所有维度)的大小都是数组类型的一部分,不能省略。
例如:
void print(int (*matrix)[10], int rowSize);
void print(int [][10]), int rowSize);

11. main函数:int main( int argc, char *argv[]){...},第一个形参argc表述数组中字符串的数量,第二个形参是数组。当实参传给main函数之后,argv的第一个元素指向程序的名字或者一个空字符串,接下来的元素依次传递命令行提供的实参。(使用argv时,一定要记得可选的实参从argv[1]开始,argv[0]保存程序的名字,最后一个指针之后的元素值保证为0。)
例如:prog -d -o ofile data0
此处argc等于5,argv应该包含如下风格的字符串:
argv[0] = "prog";
argv[1] = "-d";
argv[2] = "-o";
argv[3] = "ofile";
argv[4] = "data0";
argv[5] = 0;
 
12. 函数返回值类型。返回值的实质:返回值用于初始化调用点的一个临时量,该临时量就是函数调用的结果。
- 返回void的函数不要求有return语句,这类函数的最后一句后面会隐式地执行return。
例如:
void swap( int &v1, int &v2)
{
if(v1 == v2)
return;
int tmp =v2;
v2 =v1;
v1 =tmp;
}
- C++新标准规定,函数可以返回花括号包围的值的列表。
例如:
vector<string> process()
{
...
if(expected.empty())
return {};
else if(expected == actual)
return {"functionX","okay"};
else 
return {"functionX",expected,actual};
}
- 返回数组指针。因为数组不能被拷贝,所以函数不能返回数组。但是函数可以返回数组的指针或引用。
typedef int arrT[10];  //arrT是一个类型别名,它表示的类型是含有10个整数的数组
arrT* func(int i);     //func返回一个指向含有10个整数的数组的指针
int (*func(int i))[10]; //(*func(int i))[10]表示解引用得到的是一个大小为10的数组
- C++新标准规定了一种尾置返回类型。尾置返回类型跟在形参列表后面并以一个->开始,在本该出现返回类型的地方放置一个auto。
例如:auto func(int i) -> int (*)[10]

13. 函数指针。函数指针指向的是函数。函数的类型由它的返回值类型和形参类型共同决定,与函数名无关。
 例如:声明一个指向函数的指针
 bool (*bf)(const string &, const string &); //bf指向一个函数,未初始化
 现在我们有了一个函数:比较两个string对象的长度
 bool lengthCompare(const string &, const string &);
 pf = lengthCompare; //pf指向名为lengthCompare的函数
 pf = &lengthCompare; //等价的定义,取地址符是可选的
 pf = NULL; //初始化
 使用指向函数的指针:我们可以直接使用指向函数的指针调用该函数,无须提前解引用指针。
 bool b1 = pf("hello","goodbye");
 bool b2 = (*pf)("hello","goodbye"); //使用解引用
 bool b3 = lengthCompare("hello","goodbye");
 
- 函数指针形参。形参可以是指向函数的指针。我们可以直接把函数作为实参使用,此时它会自动转换成指针。
 例如:
 void useBigger(const string &s1, const string &s2, bool pf(const string &, const string &));
 //自动将函数lengthCompare转换成指向该函数的指针
 useBigger(s1,s2,lengthCompare);


0 0