C++ 基础知识整理

Posted baiiu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++ 基础知识整理相关的知识,希望对你有一定的参考价值。

前言

本文整理C++基础知识,用于开发中日常查阅。

引用

引用即别名,引用并非对象,它是为一个已经存在的对象所起的另一个名字。

  • 引用必须初始化
  • 引用在初始化后,不可以改变
  • 引用类型必须和绑定的对象的类型一致,但常量引用会丢失精度
  • 引用类型的初始值必须是一个变量,常量引用可以引用常量
int a = 1;
int &ra = a; // 引用必须要初始化

int c = 2;
ra = c; // 赋值操作,把c赋值给b,即赋值给a
// &rb = c; 引用在初始化后,不可以改变

// Non-const lvalue reference to type 'int' cannot bind to a temporary of type 'int'
const int e = 10;
// int &re = e; // 引用类型的初始值必须是一个对象
const int &re = e;

double d = 10.0F;
// Non-const lvalue reference to type 'int' cannot bind to a value of unrelated type 'double'
// int &rd = d; // 引用类型必须和绑定的对象的类型一致,添加const后可以
double &rd = d; 
const int &rd1 = d; // 正确,Clang-Tidy: Narrowing conversion from 'double' to 'int'

引用做函数参数

函数传参时,可以利用引用的技术,让形参修饰实参,可以简化指针修改实参。

引用做函数返回值

引用是可以作为函数的返回值存在的。函数调用作为左值。
注意:不要返回局部变量引用

//返回局部变量引用
int& test01() 
    int a = 10; //局部变量,内存分配在栈内存上,方法执行完后会回收这块内存
    return a;


//返回静态变量引用
int& test02() 
    static int a = 20;
    return a;


int main() 
    //不能返回局部变量的引用
    int& ref = test01();
    cout << "ref = " << ref << endl;
    cout << "ref = " << ref << endl;

    //如果函数做左值,那么必须返回引用
    int& ref2 = test02();
    
    // 函数调用可以作为左值
    test02() = 1000;

    return 0;

引用的本质

引用的本质在c++内部实现是一个指针常量,是所有的指针操作编译器都帮我们做了。

//发现是引用,转换为 int* const ref = &a;
void func(int& ref)
    ref = 100; // ref是引用,转换为*ref = 100

int main()
    int a = 10;

    //自动转换为 int* const ref = &a; 指针常量是指针指向不可改,也说明为什么引用不可更改
    int& ref = a; 
    ref = 20; //内部发现ref是引用,自动帮我们转换为: *ref = 20;


    func(a);
    return 0;

const关键字

const修饰变量

  • const修饰的变量也称为常量。
    使用关键字const对限定变量的值,避免其他操作改变该值,不可修改;
    const 数据类型 变量名 = 常量值

  • const对象一旦创建后就不能改变,所以必须对其进行初始化。

默认情况下,const对象仅在文件内有效。

  • 编译器在编译过程中会把用到该const变量都替换成对应的值。
    添加volatile后,可以禁止编译器对该值进行优化,必须在运行时去读取该const值。

  • 默认情况下,const对象仅在文件内有效。
    当多个文件中出现同名const变量时,其实等同于在不同文件中分别定义了独立的变量。因为在编译时会替换,所以相当于是独立的变量。

  • 可以使用extern关键字修饰,让他可以在多个文件中被共享。
    在声明和定义中都添加extern关键字,这样就只需要定义一次,别的文件也能使用该常量了。

// file1.h头文件中声明,用extern表明该const值并非本文件独有,他的定义将在别处出现
extern const int buffer_size;
// file1.cc文件中定义
extern const int buffer_size = 512;

const修饰指针

也可以用指针指向const常量或非常量。
指向常量的指针不能用于改变其所指对象的值,也只能使用指向常量的指针。

区分指针常量和常量指针,可以从右往左读,看const具体修饰的是谁。

  • 底层const,表示指针所指的对象是一个常量
    常量指针,const int *p = &PI。指针指向的值不可更改,但指针的指向可以更改。
    常量指针必须初始化,一旦初始化不可更改。

  • 顶层const,表示指针本身是个常量
    指针常量,int *const p2 = &a。指针的指向不可以改,指针指向的值可以改,

  • 当对象执行拷贝操作时,进行拷贝的对象要具有相同的底层const资格,或者这两个对象必须的数据类型必须能够互相转换。

const double PI = 3.14;
const double *p = &PI; // 正确,必须添加const关键字,即不能通过*p赋值PI,常量指针

int a = 1;
int b = 2;

// 常量指针,指针指向的值不可以改,但指针的指向可以改
const int *p = &a;
// *p = b; 错误,指向的值不可以改
p = &a; // 指针的指向可以改

// 指针常量,指针的指向不可以改,指针指向的值可以改,
int *const p2 = &a;
*p2 = b; // 指针指向的值可以改
// p2 = &b; 错误,指针的指向不可以改

// const修饰指针和常量,都不可以改
const int *const p3 = a;
// *p3 = b;
// p3 = &b;

const修饰引用

可以把引用绑定到const对象上,就像绑定到其它对象上一样,称之为对常量的引用,可以成为常量引用。
当然const也可以修饰引用,即引用非常量。

int a = 1024;
const int &ra = a;  // 正确,允许将一个常量引用绑定到普通对象上,但不允许通过ra改变a的值,a的值依然可以变化

const int b = 1024;
const int &rb = b;   // 正确,引用及其对应的常量都是常量

ra = 1;// 错误,不能修改常量
rb= 1;  // 错误,不能修改常量
int &r2 = b;  // 错误,必须是一个常量引用才行

double c = 3.14;
int &rc = c;  // 错误,类型不匹配,Non-const lvalue reference to type 'int' cannot bind to a value of unrelated type 'double'
const int &rc1 = c; // 正确,Clang-Tidy: Narrowing conversion from 'double' to 'int'

const修饰函数形参

可以使用const修饰函数入参,防止在函数体内部修改该变量

class Person 
public:
    string name;
    mutable int age;
;

void testPerson(const Person *person) 
    person->age = 1; // 可以修改
    // person->name = "aa"; // 不可修改


void testPerson(const Person& person) 
    person.age = 1; // 可以修改
    // person.name = "aa"; // 不可修改

const修饰成员函数

使用const修饰的成员函数,即常量成员函数,const成员函数内部不允许修改非mutable成员变量。

class Person 
private:
    int age; // 常量成员函数内不允许修改非mutable的值
    mutable int number; // 常量成员函数内可以修改mutable的值
public:
    int getAge() const 
        // age = 1; // 错误,不能更改
        return age;
    

    int getNumber() const 
        number = 1;
        return number;
    
;

const修饰表达式

常量表达式constexpr, const expression,是指值不会改变并且在编译过程就能得到计算结果的表达式。

const int max_file = 20;  // 常量表达式
const int limit = max_file + 1; // 常量表达式
const int size = get_size(); // 不是常量表达式,得运行时才能确定


constexpr int max= 20;  // 常量表达式
constexpr int limit = max+ 1; // 常量表达式
constexpr int sz = size(); // 只有当size()函数是一个constexpr函数时才是正确的

操作符重载

int main() 
	return 0;

模板

int main() 
	return 0;

类与对象

int main() 
	return 0;

智能指针

int main() 
	return 0;

以上是关于C++ 基础知识整理的主要内容,如果未能解决你的问题,请参考以下文章

C++ 基础知识整理

C++ 基础知识整理

C++ 基本知识整理

C++ Primer 知识总结

c++期末知识点快速复习,最全整理

初始c++——基础语法的详细讲解