C++ 学习笔记 一
以下内容为C++Primer一到三章的阅读笔记
输入输出流
iostream
库封装了一些与输入输出相关的对象与方法
- 两个基础类型
istream
与ostream
,输入流与输出流 - 4个IO对象
cin
cout
cerr
clog
- 2个运算符
<<
>>
分别作用于输出与输入对象
//简单的输入输出例程
std::cout << "hello world" << endl;
std::cin >> value;
//不定量输入
while(std::cin >> value)
变量与基本类型
基本内置类型
- 字面值常量的默认值
- 整形为
int
long
long
中的最小值 - 浮点型默认为
double
可以使用后缀来指定别的类型 - 单引号为字符 双引号为字符串
- 指针的字面值为
nullptr
- 整形为
- 指定字面值类型
- 前缀,用于指定字符串的类型
u
->Unicode 16
char16_t
U
->Unicode 32
char32_t
L
-> 宽字符wchar_t
u8
->UTF-8
只能用于字符串字面常量
- 后缀,整型、浮点型
u
unsigned
l
long
ll
long long
f
float
l
long double
- 前缀,用于指定字符串的类型
变量
- 初始化方法:4种
int a = 0;
int a = (0);
int a(0);
int a{0}; //推荐使用这种方法
- 声明与定义的关系
- 变量的声明使得改名字为编译器所知,而变量的定义则是创建于该名字相关联的实体
- 声明的方法:添加关键字
extern
- 一个变量只能被定义一次当时可以被多次声明。一个变量的定义必须也只能出现在一个文件中,而其他用到该变量的文件必须声明该变量
变量命名规范
- 变量名一般使用小写字母
- 类名一般以大些的字母开头
- 单词的区分可以采用下划线或单词首字母大写
复合类型
基本数据类型 + 声明符
引用
声明符前加上&
来表示该变量是一个引用
int value = 1000;
int &anotherValue = value
-
引用 即 取别名
-
应用实例
//修改字符串的值,在C中则需要利用指针来实现 string s{"helloworld"}; for (auto &c in s) { c = 'n' }
指针
- 指针的值应该属于下列4种情况之一
- 指向一个对象
- 指向紧邻对象所占空间的下一个位置
- 空指针,即没有指向任何对象
int *p = nullptr;//等价与 int *p = 0;
- 无效指针,其余所有值
void*
类型的指针
该指针类型从内存空间来看,其代表的只是一块内存空间,我们无法访问该指针所指向的对象,原因即我们不知道这块内存空间所存放的对象(如果有存放对象的话)是什么类型的对象
注意:引用本身不是一种对象,因此我们不能定义指向引用的指针,当是指针是一种对象,因此可以定义指针的引用(即指针的别名)
const
限定符
为了防止程序修改某个变量,可以使用const
对该变量的类型进行限定
-
const
限定的变量默认只能在一个文件中使用,如果要在别的文件中共享改变量需要在 声明 和 定义 前都是用extern
关键词加以修饰,区别于普通变量,只需要在要使用的文件中声明即可,无需在定义前也加上extern
(若加上,这样会取消extern
的作用) -
若要定义对常量的引用,该引用也必须的常量。因此对常量的引用可以绑定一个非常量的变量,但是无法通过该引用更改该非常量的值
-
注意若常量引用所绑定的对象类型与引用的类型不同,该常量引用会绑定一个临时量,这是编译器所不允许的
double davl = 3.14;
const int &ref = dacl;//×
-
同引用一样,常量指针可以指向非常量的变量,但是指向常量的指针必须是 指向常量指针(
const int *p
) -
由于指针是个对象,因此我们也可以定义常量指针(
int *const value
)区别于指向常量的指针- 常量指针意味着该指针的值(地址)是无法被改变的,但是我们可以修改该指针指向的对象的值(如果该对象不是常量的话)
- 指向常量的指针以为意味着者该指针的值(地址)存放的是一个常量变量的地址(即使该变量实际上可能并不是常量,当是该 指向常量的指针 认为该变量是常量,因此它将不去修改他的值),但是指针本身的值是可以被修改的
- 顶层
const
如上所述,指针本身是不是常量以及指针所指的对象是不是常量是两个相互独立的问题,我们用名词顶层const
来表示变量的本身是常量,用底层const
来表示变量所指的对象是常量
-
现在注意一个问题,我们先前说过,一个指向常量的指针(引用)可以指向一个非常量变量,但是要指向常量必须使用指向常量的指针(引用)。这个意为着当执行对象拷贝操作时,拷入与拷出的对象都必须具有相同的底层
const
资格,或者两个数据类型可以相互转化,即非常量可以转化为常量
constexpr
变量
区别与const
修饰的常量,constexpr
常量(函数)要求在也只能在编译的时候就确定该常量的值,而const
常量只需要在运行的时候其值不能被改变就可以,并不一定要在编译的时候就确定它的值。
特别体现在类中,成员变量的指针可以用const
修饰但是不能用constexpr
修饰。原因是类的变量的地址在运行的时候才能确定。
auto
与 decltype
auto
用于更具赋值的表达式自动推算类型decltype
用于更具指定的表达式推断类型
字符串、向量和数组
命名空间
- 因为很多类的名字可能会重复,因此需要命名空间。命名空间即一个储存了很多变量名的空间,在使用这个空间的名字的时候,需要使用这个命名空间
using namespace_name::name
或using namespace namespaec_name
字符串string
- 字符串字面值 与
string
不是同个类型的变量(为了兼容C) - 一些新的运算符
>>
输出到流<<
输入到字符串,以空格为分隔符getline()
获取一整行+
>
>=
<=
<
==
等
向量vector
是一种模版
-
初始化方法(必须使用直接初始化)
用
=
为拷贝初始化用
()
{}
为直接初始化
()
构造初始化
{}
列表初始化vector
myVector{1,23,4}; vector myVector(10,1);//10个1 -
动态添加元素
vector
myVector; int temp; while(cin >> temp) myVector.push_back(temp); -
注意:不能用下标的方式添加元素,因为该下标访问的地方是还没有定义的会造成内存溢出
vector
my; my[0] = 42;//×
迭代器iterator
所有的标准库容器都可以迭代器,但是其中只有少数几种才支持下标运算符[]
类似于指针的概念,其对象是容器中的元素或字符串中的字符
-
一个简单的示例
//遍历字符串中的字符并且输出 string s{ "hello world" }; for (auto myit = s.begin();myit != s.end(); myit++) cout << * myit;
-
注意 在使用迭代器的时候不要对迭代器所迭代的对象添加元素,否则会导致迭代器失效
-
迭代器的算数运算
+ - > < == * /
类似与下标之间的运算
-
指向常量的迭代器
.cbegin() 与 .cend()
两个函数放回的都是指向常量的迭代器,我们无法使用该迭代器修改迭代器所指向的元素
数组
指针与数组
等同于C语言中的指针与数组,但增加了两个计算数组头指针与尾指针的函数begin()
end()
int a[10];
int *pend = end(a);//等同于 int *pend = &a[10]
if (end(a) == &a[10])
cout << true;
//运行结果为 1
- 指针与指针相减会放回他们之间的距离 类型为
ptrdiff_t
下标运算
下边可以使用带符号的整型参与运算
int a[10];
int *p = a+2//等价于 int *p = &a[2]
if (*a == p[-2])
cout << true;
//结果为 1
多维数组
内容略