[C++] C++ Primer 笔记

这篇博客详细介绍了C++ Primer中的关键概念,包括类的行为定义、算术类型、内置类型实现、强制类型转换规则、引用和指针、const限定符、初始化、以及指针和数组的相关操作。文章深入探讨了类型转换、常量引用、指针与const的关系、泛型编程、函数重载和作用域等主题,还涵盖了C++中的异常安全和预处理宏等内容。
摘要由CSDN通过智能技术生成

1. 类定义了行为

它为了说明”类定义了行为“,直接给出一个定义好运算符重载的类……有点跳跃

在这里插入图片描述

2. 算术类型

在这里插入图片描述

一个 int 至少和一个 short 一样大
一个 long 至少和一个 int 一样大
一个 long long 至少和一个 long 一样大
其实就是说
short ≤ int ≤ long ≤ long long

3. 内置类型的机器实现

在这里插入图片描述
在这里插入图片描述

4. 强制类型转换的规则

在这里插入图片描述

总的来说,范围大的和范围小的一起用,会转换为范围小的
无符号相对有负号是另一种意义上的范围小

5. 字面值的类型

在这里插入图片描述

6. 初始化

指定初值:xian
没有指定初值:默认初始化
制定列表{}:列表初始化

默认初始化:
定义在函数体外部的变量被初始化为 0
定义在函数体内部的变量将不被初始化

包含了显式初始化的声明即成为定义

要声明一个变量,在前面添加 extern,并且不显式初始化

变量能且只能被定义一次,但是可以被多次声明

7. 引用

引用不是对象,没有实际地址,所以不能定义指向引用的指针

8. 指针

初始化为 nullptr

9. 其他指针操作

在这里插入图片描述

对这句话的理解:
https://www.php.cn/wenda/70513.html

在这里插入图片描述

已知:end() 返回指向容器最后一个数据单元+1的指针

”指针指向另一个对象的下一个地址“不难理解,令人困惑的是,为什么非要说”下一个“,它有什么特殊含义吗?指针是有什么特殊操作可以在初始化的时候指向初始化右侧值得下一个地址吗?不是得。他其实是说,经过某一段程序之后,指针的地址可能会被多次修改,改到最后才等于”一个对象的下一个地址“

10. void*

和别的指针比较
作为函数的输入或输出
或赋给另外一个 void*

11. 理解复合类型的声明

int* p; 中,int 是基本数据类型,* 是类型修饰符,修饰 p 而不是 int
因此 int* p1, p2; 中,p1 是 int 类型的指针,p2 是 int,因为 * 只修饰了 p1

12. 指向指针的引用

在这里插入图片描述

13. const 限定符

const 的常量特征仅仅在执行改变本常量的操作时才会发挥作用,故初始化可以用 const 或其他

默认状态下,const 对象仅在文件内有效
想在多个文件之间共享 const 对象,必须在变量的定义之前添加 extern 关键字

14. 常量引用

常量引用实际上是对常量的引用

在这里插入图片描述

常量引用的引用对象不一定是常量

在这里插入图片描述

15. 初始化和对 const 的引用

在这里插入图片描述
类型转换时,编译器把代码变成:”赋值语句右值类型转换为临时值,临时值赋给赋值语句左值“
那么如果赋值语句的左值是非常量引用,那么他绑定的这个临时值之后,对这个非常量引用的修改,只会关联到对临时值的修改,这是没有用的,我们拿不到这个临时值。所以非常量引用的赋值语句右侧不能出现类型转换,也就是”非常量引用的类型必须与其所引用对象的类型保持一致“
但是常量引用没有关系,因为就算是绑定到了临时值,我也不修改常量引用,我只是读而已,读常量跟我这个常量引用绑定到哪里没有关系。所以”常量引用的类型不用与其所引用对象的类型保持一致“

16. 指向常量的XX 常量XX

指向常量的XX 即不规定所指的对象必须是一个常量,而是要求不能通过 XX 改变对象的值,自然,对象的值可能通过其他途径改变

常量XX XX本身不变

XX 指代指针或者引用

例外是,引用不是对象,所以不能规定引用自身不变,所以没有常量引用
但是把指向常量的引用简称为常量引用

const <T> &var //指向常量的引用 不能被用作修改他所绑定的对象
const <T> *var //指向常量的指针 不能被用作修改他所指向的对象
<T> *const var //常量指针 指针本身是常量

声明的理解:
1.从右往左读
2.const 修饰 const 出现地点左边的声明类型
3.如果左边没有声明类型,就修饰右边

17. 顶层 const

在这里插入图片描述

const <T> &var //指向常量的引用 不能被用作修改他所绑定的对象 底层 const
const <T> *var //指向常量的指针 不能被用作修改他所指向的对象 底层 const
<T> *const var //常量指针 指针本身是常量 顶层 const

初始化时,
非常量 左值 = 顶层 const 右值
底层 const 左值 = 底层 const 右值
底层 const 左值 = 非常量 右值
顶层 const 左值 = 顶层 const 左值
顶层 const 左值 = 底层 const 左值
顶层 const 左值 = 非常量 右值
啊……这样写……有点麻烦,毕竟是4*4的情况
我希望根据一些简单的原则来判断是否合法,比如,不能违背右值设定的原意什么的
因为“底层 const”意味着需要保证指向的对象是一个常量,如果把这个地址给一个别的非底层 const 的变量,就意味着有可能通过这个别的非底层 const 的变量更改指向的对象,这与保证冲突了。

如果不想死记的话,尝试通过 const 的约束判断赋值是否合法也行,因为这就是编辑器的做法
比如

const double pi = 3.14;
double *ptr = &pi;

不考虑规则,& 是取地址,pi 是常量,那么 &pi 就是一个指向常量的地址,但是左值是一个普通的地址
不能通过普通的地址改变作为常量的对象,所以这个赋值不合法

报错也就容易理解了

error: invalid conversion from 'const double*' to 'double*' [-fpermissive]
     double *ptr = &pi;

又比如,向顶层 const 左值的声明没有限制,因为我只是把右值作为左值指向的对象,不管右值有什么约束,我左值都不会动它,所以我左值来者不拒

18. 指针和 constexpr

constexpr 把它所定义的对象置为了顶层 const

19. 指针、常量和类型别名

在这里插入图片描述

20. 复合类型、常量和 auto

在这里插入图片描述

21. decltype 和引用

在这里插入图片描述

22. 头文件不应包含 using 声明

在这里插入图片描述

23. 直接初始化和拷贝初始化

直接初始化使用括号

24. getline

在这里插入图片描述

25. size_type 类型

在这里插入图片描述

26. 字面值与 string 对象相加

在这里插入图片描述

27. C++ 版本的 C 标准库头文件

在这里插入图片描述

28. 使用基于范围的 for 语句

for (declaration:expression)
	statement

循环变量定义成引用类型,这个变量实际上被依次绑定到了序列的每个元素上

这个是可以正常运行的

int my_array[5] = {
    1, 2, 3, 4, 5 };

// 不会改变 my_array 数组中元素的值
// x 将使用 my_array 数组的副本
for (int x : my_array)
{
   
    x *= 2;
    cout << x << endl;
}

但是这个就不可以

#include <iostream>
using namespace std;  

void print(const int arr[10])
{
   
    for (auto num : arr)
    {
   
        cout<<num;
    }
    
    return;
}
int main()
{
   
    const int arr[3] = {
   1,2,3};
    print(arr);
}

报错为

test.cpp: In function 'void print(const int*)':
test.cpp:6:21: error: 'begin' was not declared in this scope
     for (auto num : arr)
                     ^~~
test.cpp:6:21: note: suggested alternative:
In file included from D:/Tools/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/string:51,
                 from D:/Tools/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/locale_classes.h:40,
                 from D:/Tools/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/ios_base.h:41,
                 from D:/Tools/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/ios:42,
                 from D:/Tools/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/ostream:38,
                 from D:/Tools/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/iostream:39,
                 from test.cpp:1:
D:/Tools/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/range_access.h:105:37: note:   'std::begin'
   template<typename _Tp> const _Tp* begin(const valarray<_Tp>&);
                                     ^~~~~
test.cpp:6:21: error: 'end' was not declared in this scope
     for (auto num : arr)
                     ^~~
test.cpp:6:21: note: suggested alternative:
In file included from D:/Tools/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/string:51,
                 from D:/Tools/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/locale_classes.h:40,
                 from D:/Tools/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/ios_base.h:41,
                 from D:/Tools/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/ios:42,
                 from D:/Tools/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/ostream:38,
                 from D:/Tools/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/iostream:39,
                 from test.cpp:1:
D:/Tools/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/range_access.h:107:37: note:   'std::end'
   template<typename _Tp> const _Tp* end(const valarray<_Tp>&);
                                     ^~~

改成了

#include <iostream>
using namespace std;  

void print(int arr[10])
{
   
    for (auto num : arr)
    {
   
        cout<<num;
    }
    
    return;
}
int main()
{
   
    int arr[3] = {
   1,2,3};
    print(arr);
}

还是一样的报错

我再稍微改了一下:

#include <iostream>
using namespace std;  

void print(int arr[10])
{
   
    for (auto num : arr)
    {
   
        cout<<num;
    }
    
    return;
}
int main()
{
   
    int myarr[10] = {
   1,2,3,4,5,6,7,8,9,10};
    print(myarr);
}

这个时候我确实能够看到,编辑器自己都能在我悬浮鼠标到 for 中的 arr 时联想到 int arr[10]

在这里插入图片描述

但是运行的时候他就是说没有

然后我有一个同学说 for range 不能用于静态数组,我改成了

#include <iostream>
using namespace std;  

void print(int arr[])
{
   
    for (auto num : arr)
    {
   
        cout<<num;
    }
    
    return;
}
int main()
{
   
    int myarr[10] = {
   1,2
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值