重读c++primer(基础部分)

C++是那种让人又爱又恨的语言,爱她的理由有很多,恨她估计也只有一点,就是她太复杂多变,需要认真的熟悉她,记忆她的点点滴滴,每个细节,才能和她很好的相处。

而c++primer就像是C++的日记本,想要了解她,翻开这本书,无疑于是最好的办法。

那么,我们就开始吧。

变量和基本类型

  • 在写c++程序时,大部分出现空格的地方都可以用换行符代替。

    1
    2
    3
    4
    std::cout<<"The sum of"<<v1
    <<"and"
    <<v2
    <<"is"<<v1+v2<<std::endl;
  • c++中,对于很长的字符串可以通过使用反斜杠符号分行:

    1
    2
    std::cout<<"Hell\
    o!!!!!world!"<<std::endl;
  • 给变量定义一个初始值几乎始终是正确的,虽然不要求必须这么做。

  • 通常最好的是将一个注释块放在所解释的代码的上方。

  • c++中把负数赋给unsigned对象是完全合法的,其结果为该负数对该类型的取值数的求模后的值。例如:

    把-1赋给8位的unsigned char,那么结果为255,因为255是-1对256求模后的值。

  • 决定用哪种浮点型,使用double基本上不会有错。

  • unsigned int类型可以简写成unsigned

左值和右值

  • 左值:左值可以出现在赋值语句的左边或右边
  • 右值:右值只能出现在赋值的右边,不能出现在赋值语句的左边

区分左值右值的真正说法是:能否用“取地址&”运算符获得对象的内存地址。

对于临时对象,它可以存储于寄存器中,所以是没办法用“取地址&”运算符;

对于常量,它可能被编码到机器指令的“立即数”中,所以是没办法用“取地址&”运算符;

字符串字面值常量是C++标准中明确指明的特例,为常量左值,所以可以取地址&运算,其地址属于进程的只读内存空间。其它的字面值常量都是“纯右值”。

extern

1
2
3
4
5
6
7
//c++程序中变量可以声明多次,但只能定义一次
//当定义变量时我们声明了它的类型和名字,可以通过使用extern关键字声明变量名而不定于它
//已初始化的extern被当做是定义,所以该变量任何随后的定义都是错误的
extern double pi=3.14159;//definition
double pi;//error
extern double pi;//ok,declaration not definition
extern double pi = 3.14159;//error,redefinition of pi

c++全局作用域中,非const变量默认为extern,

要使const变量能够在其他的文件中访问,必须显式的指定它为extern

1
2
3
4
5
6
7
8
> //非const对象
> //file1.c
> int a;
>
> //file2.c
> extern int a;
> a++;
>

>

1
2
3
4
5
6
7
8
9
> //const 对象
> //file1.c
> extern const int ca=666;//要想其他文件中能访问const对象,定义时要显式的说明是extern
>
> //file2.c
> extern const int ca;
> std::cout<<ca<<std::endl;
>
>

引用

引用是别名

1
2
3
4
5
6
> int ival=1024;
> int &refval = ival;
> int &reval2;//error:a reference must be initialized
> int &redval3 = 10;//error,initializer must be an object
> //引用声明时必须赋初值,被引用的必须是一个对象名。
>

const对象得用const引用

1
2
const int ival =1024;
const int &refVal=ival;

枚举

默认的,第一个枚举成员赋值为0,每个枚举成员默认赋值只看前一位,后面的比前一位大1.

枚举成员是常量。不可以改变枚举成员的值,枚举成员本身就是个常量表达式,并且可以用在需要常量表达式的任何地方。

使用枚举例子:

1
2
3
4
enum Points{point2d = 2 , point2w , point3d = 3 , point3w};//point2w默认初始化为3, point3w,默认初始化为4.(前一个的数值加1)
Points pt3 = point3d;//枚举类型赋值
Pointd pt2w = 3 ;//error 枚举类型赋值必须用枚举类型来赋值,即使3与一个枚举成员相关也不可以

类类型

用class和struct关键字定义类的唯一差别在默认的访问级别:默认情况下,struct的成员为public,而class成员为private。

设计头文件

头文件一般包含 类的定义、extern 变量的声明 、函数的声明。

头文件的好处:保证所有文件使用给定实体的同一声明;当声明需要修改时,只有头文件需要更新。

下面语句是一些定义,不应该放在头文件里:

1
2
extern int ival = 10; //initializer,so it is a definition
double fin; // no extern,so it is a definition

同一个程序中有两个以上文件含有 上述任一定义都会导致多重定义链接错误。

因为头文件包含在多个源文件中,所以不应该含有变量或函数的定义。

对于头文件不应该含有定义这一规则,有三个例外。头文件可以定义 类、值在编译时就已经找到的const对象 和 inline函数。这些实体可以在多个源文件中定义,只要每个源文件中的定义是相同的。

但是,c++中任何变量都只能定义一次。定义会分配存储空间,而所有对该变量的使用都关联到同一存储空间。因为const对象默认为定义它的文件的局部变量,所以把它们定义放在头文件中是合法的。

如果const变量不是用常量表达式初始化,那么它就不应该在头文件中定义。相反,和其他的变量一样,该const变量应该在一个源文件中定义并初始化。应在头文件中为它添加extern声明,以使其能被多个文件共享。

设计头文件时,应使其可以多次包含在同一源文件中:

例如 写了 sales_item 的类的头文件,里面包含了string库,另一个程序A也包含string库,A包含进A程序,string头就被包含了两次,但是并不影响。

因为通过使用 预处理定义 头文件保护符 可以避免多重包含出现的多次定义问题。

1
2
3
4
5
#ifndef SALESITEM_H
#define SALESITEM_H
...
...
#endif

附注:头文件中应该只定义确实必要的东西。

标准库类型

比较好的using声明:

1
2
3
4
5
using std::cin;
using std::cout;
using std::endl;
#include<string>
using std::string;

string

对象读写

  • 从标准输入读取string:
    • 读取并忽略开头所有的空白字符
    • 读取字符直到再次遇见空白字符
  • 用 getline读取整行文本
    • 遇到换行符才返回,并丢弃换行符,不保存换行符。

string 关系操作符

在多数计算机上,大写的字母位于小写字母之前:任何一个大写字母都小于任意的小写字母。

  • 字符串字面值链接
1
2
3
4
string s1 = "hello";
string s2 = "world";
string s3 = s1 +","; //OK
string s4 = "hello"+",";//error 不能是两个字符串字面值相加,“+”运算符两边至少要有一个是string类型

本文标题:重读c++primer(基础部分)

文章作者:Yang Shuai

发布时间:2018年05月27日 - 16:05

最后更新:2018年05月27日 - 16:05

原始链接:https://ysbbswork.github.io/2018/05/27/重读c-primer(基础部分)/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

坚持原创技术分享,您的支持将鼓励我继续创作!