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

struct 类型加强

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

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

第一章 - C++基础特性

作用域运算符的使用

namespace Maker
{
	int c =30;
}
int main()
{
	cout << Maker::c << endl;
}
//命名空间可以取别名,例如:
namespace Maker1 = Maker;


三目运算符对比

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

/* 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. 引用的语法

    //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. 引用的注意:

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

数组引用

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不重视作用域,不能限定常量的使用范围

指针引用

//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. 引用作为函数参数

    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. 作为函数的返回值

    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. 常量引用

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

内联函数

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 输入验证实现

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

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];
}
#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;
}