本文是几年前学习C++ Primer Plus过程中整理的一些知识点,无意间翻到,没有什么技术含量,简单记录一下。

struct 类型加强

C++对C语言的结构体进行了重要增强:

  1. 定义变量时不需要使用 struct 关键字
  2. 结构体内可以直接定义成员函数

第一章 - C++基础特性

作用域运算符的使用

1
2
3
4
5
6
7
8
9
10
11
12
namespace Maker
{
int c =30;
}
int main()
{
cout << Maker::c << endl;
}
//命名空间可以取别名,例如:
namespace Maker1 = Maker;


三目运算符对比

C与C++的三目运算符有本质区别:

1
2
3
4
5
6
7
8
9
10
11
/* C 语言实现方式 */
int a = 10, b = 20;
*(a > b ? &a : &b) = 100; // 必须通过指针操作
// 等号左侧需要可修改的左值,因此需要取地址操作

//-----------------------------------------

/* C++ 实现方式 */
int x = 10, y = 20;
(x > y ? x : y) = 100; // 直接赋值
// 返回变量引用(左值),类型安全且无需取地址

主要改进:

  1. 类型系统更严格,避免指针操作风险
  2. 返回值可直接作为左值使用
  3. 代码可读性更好,更符合面向对象思维

C++ 不能优化的情况

  1. 不能优化自定义数据类型
  2. 如果用变量给const修饰的局部变量复制,不能优化
  3. 编译器在编译阶段来优化数据

C和C++的区别

  1. C语言的结构体不能写函数,C++可以
  2. 结构体定义变量时,C++不需要加struct关键字
  3. 更加严格的类型检查
  4. const修饰的变量,C++有时没有内存,C语言的都有内存
  5. 三亩运算符返回值不一样
  6. 引用和C的指针功能一样

引用

  1. 引用是和C语言的指针一样的功能

  2. 引用是给空间取别名

  3. 引用的语法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    //C语言中指针
    int a = 10;
    int *p = &a;
    *p = 100;
    //这样输出a是100;

    int a = 10;
    int &b = a; //给a的空间取别名叫b,标志作用。现在a和b都代表那一个空间
    b = 100
    cout << a << endl; //输出为100

    //C++引用的使用
    void func(int &a)
    {
    a = 200;
    }
    void test02()
    {
    int a =10;
    func(a);
    cout<< "a= "<< endl;
    }
  4. 引用的注意:

    1
    2
    3
    引用创建时,必须初始化
    引用一旦初始化,不能改变他的指向
    引用必须用一块合法的内存空间
    1
    2
    3
    4
    5
    6
    7
    int a = 10;
    int &pac = a; //取别名
    int b = 20;
    pac = b; //赋值操作
    cout << &a << endl;
    cout << &pac << endl;
    //得出相同值

数组引用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
int main()
{
int arr[] = {1, 2, 3, 4, 5};
// 第一种方法
typedef int(My_Arr)[5];
// 建立引用
My_Arr &arref = arr; // 建立引用,int &b = a;

// 第二种方法
// 直接引用
int(&arref2)[5] = arr; // int &b = a;

// 第三种方法
typedef int(&My_Arr3)[5]; // 建立引用数组类型
My_Arr3 arref3 = arr;

for (int i = 0; i < 5; i++)
{
cout << arref[i] << endl;
}

for (int i = 0; i < 5; i++)
{
arref2[i] = 100 + i;
cout << arref2[i] << endl;
}
}

使用const代替define

  1. define没有数据类型,const修饰的变量有数据类型,可以进行数据类型检查
  2. const修饰的变量有作用域,define不重视作用域,不能限定常量的使用范围

指针引用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
//C语言版本
void func(char * *tmp)
{
char *p;
p = (char *)malloc(64);
memset(p, 0, 64);
strcpy(p, "小花");
*tmp = p;
}

void test02()
{
char *mp = NULL;
func(&mp);
cout << mp << endl;
}


//C++版本
void func(char *&tmp)
{
char *p;
p = (char *)malloc(64);
memset(p, 0, 64);
strcpy(p, "小花");
tmp = p; // 省了*
}

void test02()
{
char *mp = NULL;
func(mp); // 省了&
cout << mp << endl;
}

image-20230224173319252


引用的使用场景

  1. 引用作为函数参数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    void func(int &a,int &b)
    {
    int sum = a + b;
    cout << "sum= " << sum << endl;
    }
    void test01()
    {
    int a = 10;
    int b = 20;
    func(a,b);
    }
  2. 作为函数的返回值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    int &func2()
    {
    int b = 10;//注意1.不要返回局部变量的引用
    int &p = b;
    return p;
    }
    int &func3()
    {
    static int a = 10;
    return a;
    }

    void test2()
    {
    int &q = func2();
    q = 100;
    cout << q << endl;
    //输出100
    func2() = 200;
    cout << q << endl;
    //-------上面是代码错误,只是编译器没有检测出来
    //输出200,但是错误
    cout << "func2= " << func2() << endl;
    //输出10,没有改变
    func3() = 199; //注意2.如果要函数当左值,那么该函数必须返回引用
    cout << "func3 = " <<func3()<< endl;
    //输出199,成功改变
    }

  3. 常量引用

    1
    2
    3
    4
    5
    6
    7
    8
    //普通引用
    int a = 10;
    int &ref = a;
    ref = 20;

    // int &ref2 = 10;//不能给字面量取别名
    const int &ref3 = 10;//可以给const修饰的引用赋予字面量
    // 编译器会把上面的代码变为:int tmp =10;const int &ref3 =tmp;

内联函数

1
2
3
4
inline int func(int x,int y)
{
return x < y ? x : y;
}

何时不会成为内联函数:

  1. 存在过多的条件判断语句
  2. 函数体过大
  3. 对函数进行取址操作

内联函数的好处:

  1. 有宏函数的效率,没有宏函数的缺点
  2. 类的成员函数默认加上 inline

第四章

程序执行的四步:预处理,编译,汇编,链接

每次读取一行字符串输入

getline ()
读取整行,使用回车键的换行符来确定结尾。使用 cin.getline 调用
注意:getline 不读取换行符,而 cin.get 的读取换行符
get ()
cin.get 调用 cin. get ( char , int )
注意:get 读取换行符,每次使用后要再使用一次 cin.get()来把换行符读取走
推荐使用 cin. get ()

何时使用句点运算符,何时使用箭头

如果结构标识符是结构名,则使用句点运算符;如果标识符是指向结构的指针,则使用箭头运算符。

第六章

6.7 输入验证实现

实现安全的数字输入循环:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
for (int i = 0; i < Max; i++)
{
std::cout << "Round#" << (i + 1) << ": ";

// 输入验证循环
while (!(std::cin >> golf[i]))// 如果用户输入错误
{
// 重置输入流状态
std::cin.clear();

// 清除错误输入
while (std::cin.get() != '\n') {
continue;
}

std::cout << "Invalid input. Please enter a number: ";
}

total += golf[i];
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include<iostream>

const int Max = 5;
int main()
{
using namespace std;
int golf[Max];
double total = 0.0;
cout << "Please enter your scores you mast enter "
<< Max << " courses" << endl;

for (int i = 0; i < Max;i++)
{
cout << "Round# " << i + 1 << ":";
while (!(cin >> golf[i])) // 如果用户输入错误
{
cin.clear(); //重置输入
while (cin.get()!='\n') //清除输入
continue;
cout << "Please enter a number: ";
}
total += golf[i];
}

cout << "average score is: " << total / Max << endl;
return 0;
}