跳到主要内容 C++ 进阶笔记:引用、重载与内存管理 | 极客日志
C++ 算法
C++ 进阶笔记:引用、重载与内存管理 介绍 C++ 核心概念,涵盖引用与指针的区别、函数重载规则、构造函数与初始化列表、this 关键字用法、动态内存分配 new/delete、析构函数及静态成员。通过代码示例演示了引用作为别名的特性、重载的匹配机制、构造函数的初始化顺序以及内存管理的正确实践,帮助读者理解 C++ 面向对象编程的基础与内存安全。
芝士奶盖 发布于 2026/3/23 更新于 2026/4/17 19K 浏览八、引用
引用变量是一个别名,也就是说,它是某个已存在变量的另一个名字。类似于给你取一个新的呼叫名,比如你叫李华,我可以叫你小华(当公司只有你一个带华字的),等于说我可以通过这个呼叫你(直接访问)。
引用相当于给这个内存中的数据提供了一个新的变量名。(我脑子存储了你叫小华)
引用很容易和指针混淆。
引用和指针的区别
不存在空引用。引用必须连接到一块合法的内存。
一旦引用被初始化为一个对象,就不能被指向到另一个对象。指针可以在任何时候指向到另一个对象。
引用必须在创建时被初始化。指针可以在任何时间被初始化。
可以说变量名是变量在内存中的第一个名字,对它的引用是其第二个名字;
int a=6 ; int * p=&a; *p=20 ;
可以为 a 声明引用变量
int & r = a; double & s = d;
&读作引用 。第一个声明读作'r 是一个初始化为 i 的整型引用',第二个同理。**
特性 引用 (Reference) 指针 (Pointer) 声明语法 int& ref = var; int* ptr = &var 是否可为空 不可为空,必须绑定有效对象 可为 nullptr 是否可重新绑定 一旦绑定,不可更改目标 可随时指向其他变量或 nullptr 访问目标值 直接使用 ref 需解引用 *ptr 内存地址存储 不存储地址,是变量的别名 存储变量的地址
#include <iostream>
using namespace std;
int main () {
int value = 10 ;
int & ref = value;
ref = 20 ;
cout << << value << endl;
* ptr = &value;
*ptr = ;
cout << << value << endl;
newValue = ;
ptr = &newValue;
*ptr = ;
cout << << newValue << endl;
ptr = ;
cout << << endl;
cout << << &value << endl;
cout << << &ref << endl;
cout << << &ptr << endl;
cout << << ptr << endl;
;
}
微信扫一扫,关注极客日志 微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
相关免费在线工具 加密/解密文本 使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
Base64 字符串编码/解码 将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
Base64 文件转换器 将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
Markdown转HTML 将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
HTML转Markdown 将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
JSON 压缩 通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online
"引用修改后 value = "
int
30
"指针修改后 value = "
int
40
50
"newValue = "
nullptr
"\n 内存地址:"
"value 地址:"
"ref 地址:"
"ptr 地址:"
"ptr 指向的地址:"
return
0
#include <iostream>
using namespace std;
double val[]={10.1 ,12.6 ,33.1 ,24.1 ,50.0 };
double & setValue (int i) {
double & ref = val[i];
return ref;
}
int main () {
setValue (3 ) = 90.9 ;
cout<< val[3 ] ;
return 0 ;
}
返回引用时,要注意被引用的对象不能超出作用域。所以返回一个局部变量的引用是不合法的。
int & fun () {
int q;
static int x;
return x;
}
为什么通过函数可以修改数组?
setValue 返回的是 val[i] 的引用(double&),而不是它的拷贝。
对引用的修改会直接影响原始数组元素 ,因为引用是原始数据的'别名'。
函数类型 示例代码 修改是否生效 返回引用 double& setValue(int i) 修改原始数组 返回值 double setValue(int i) 只修改函数内副本
引用(Reference):一旦初始化就无法改变指向,必须绑定到一个有效的对象,且生命周期与原对象一致。就像'我注定只能是你'。
指针(Pointer):可以随时改变指向,甚至可能悬空(dangling pointer)或指向 null,象征关系的不确定性。
九、重载
函数重载 在同一个作用域内,可以声明几个功能类似的同名函数;
C++ 中,函数重载 是指 在同一作用域内,可以有多个同名函数,但它们的参数列表不同(参数的类型、个数或顺序不同) 。编译器会根据调用时传入的实参来自动选择匹配的函数。
函数重载的规则:
函数名必须相同
参数列表必须不同(以下任一):
返回类型可以不同,但不能仅靠返回类型不同来重载
#include <iostream>
using namespace std;
int add (int a, int b) {
cout << "调用两个参数的 add" << endl;
return a + b;
}
int add (int a, int b, int c) {
cout << "调用三个参数的 add" << endl;
return a + b + c;
}
int main () {
cout << add (2 , 3 ) << endl;
cout << add (2 , 3 , 4 ) << endl;
return 0 ;
}
#include <iostream>
using namespace std;
void printSum (int a, int b) {
cout << "整数和:" << a + b << endl;
}
void printSum (double a, double b) {
cout << "浮点数和:" << a + b << endl;
}
int main () {
printSum (3 , 5 );
printSum (3.5 , 6.7 );
return 0 ;
}
#include <iostream>
using namespace std;
void show (int a, string s) {
cout << "int: " << a << ", string: " << s << endl;
}
void show (string s, int a) {
cout << "string: " << s << ", int: " << a << endl;
}
int main () {
show (10 , "Hello" );
show ("World" , 20 );
return 0 ;
}
#include <iostream>
using namespace std;
void greet (string name) {
cout << "Hello, " << name << "!" << endl;
}
int main () {
greet ("Alice" );
return 0 ;
}
#include <iostream>
using namespace std;
class Rectangle {
private :
int width, height;
public :
Rectangle () {
width = 1 ; height = 1 ;
cout << "调用无参构造函数" << endl;
}
Rectangle (int w) {
width = w; height = w;
cout << "调用单参构造函数" << endl;
}
Rectangle (int w, int h) {
width = w; height = h;
cout << "调用双参构造函数" << endl;
}
void showArea () {
cout << "面积:" << width * height << endl;
}
};
int main () {
Rectangle r1;
Rectangle r2 (5 ) ;
Rectangle r3 (3 , 4 ) ;
r1. showArea ();
r2. showArea ();
r3. showArea ();
return 0 ;
}
十、构造函数 类的构造函数是类的一种特殊的成员函数,它会在每次创建类的新对象时执行。
构造,构造的是什么:构造成员变量的初始值,内存空间等
构造函数的名称与类的名称是完全相同的,并且不会返回任何类型,也不会返回 void。构造函数可用于为某些成员变量设置初始值。
#include <iostream>
#include <string>
class Book {
private :
std::string title;
std::string author;
int pages;
bool is_borrowed;
public :
Book () {
title = "未知标题" ;
author = "未知作者" ;
pages = 0 ;
is_borrowed = false ;
std::cout << "调用了默认构造函数,创建了一本新书。\n" ;
}
Book (const std::string& t, const std::string& a) {
title = t;
author = a;
pages = 0 ;
is_borrowed = false ;
std::cout << "调用了带参数的构造函数,创建了《" << title << "》。\n" ;
}
Book (const std::string& t, const std::string& a, int p) {
title = t;
author = a;
pages = p;
is_borrowed = false ;
std::cout << "调用了带参数的构造函数,创建了《" << title << "》,共 " << pages << " 页。\n" ;
}
~Book () {
std::cout << "《" << title << "》这本书被销毁了。\n" ;
}
void borrow () {
if (!is_borrowed) {
is_borrowed = true ;
std::cout << "《" << title << "》已被借出。\n" ;
} else {
std::cout << "《" << title << "》已在借阅中。\n" ;
}
}
void returnBook () {
if (is_borrowed) {
is_borrowed = false ;
std::cout << "《" << title << "》已归还。\n" ;
} else {
std::cout << "《" << title << "》未被借出。\n" ;
}
}
void displayInfo () const {
std::cout << "书名:" << title << "\n作者:" << author << "\n页数:" << pages << "\n状态:" << (is_borrowed ? "已借出" : "在馆" ) << "\n" ;
std::cout << "------------------------\n" ;
}
};
int main () {
std::cout << "--- C++ 构造函数与对象实例化演示 ---\n\n" ;
std::cout << "创建 book1 (使用默认构造函数):\n" ;
Book book1;
book1. displayInfo ();
std::cout << "\n创建 book2 (使用带参数的构造函数):\n" ;
Book book2 ("C++ Primer" , "Stanley Lippman" ) ;
book2. displayInfo ();
std::cout << "\n创建 book3 (使用带参数的构造函数):\n" ;
Book book3 ("Effective C++" , "Scott Meyers" , 250 ) ;
book3. displayInfo ();
std::cout << "\n--- 演示对象方法 ---\n" ;
book2. borrow ();
book2. displayInfo ();
book3. borrow ();
book3. borrow ();
book3. displayInfo ();
book2. returnBook ();
book2. displayInfo ();
std::cout << "\n--- 程序结束,局部对象将被自动销毁 ---\n" ;
return 0 ;
}
初始化列表
初始化列表是构造函数的一部分,用于在构造函数体执行前初始化成员变量。
必须使用初始化列表的场景:const 成员、引用成员、无默认构造函数的类成员。
初始化顺序由类中声明的顺序决定,与初始化列表中的顺序无关
class MyClass {
private :
int a;
double b;
std::string c;
public :
Myclass (int x,double y,const std::string& z):a (x),b (y),c (z){
}
};
#include <iostream>
using namespace std;
class Helper {
public :
Helper (int value) {
cout << "Helper 构造函数:value = " << value << endl;
}
};
class MyClass {
private :
int normalVar;
const int constVar;
int & refVar;
Helper helper;
public :
MyClass (int a, int b, int c) : normalVar (a),
constVar (b),
refVar (c),
helper (c)
{
cout << "MyClass 构造函数体" << endl;
}
void printValues () const {
cout << "normalVar: " << normalVar << endl;
cout << "constVar: " << constVar << endl;
cout << "refVar: " << refVar << endl;
}
};
int main () {
int value = 42 ;
MyClass obj (10 , 20 , value) ;
obj.printValues ();
return 0 ;
}
this 关键字 在 C++ 中,this 关键字是一个指向调用对象的指针。它在成员函数内部使用,用于引用调用该函数的对象,使用 this 可以明确指出成员函数正在操作的是哪个对象操作的数据成员。
#include <iostream>
#include <string>
using namespace std;
class Person {
private :
string name;
int age;
public :
Person (string name, int age) {
this ->name = name;
this ->age = age;
}
void setName (string name) {
this ->name = name;
}
void setAge (int age) {
this ->age = age;
}
Person& setInfo (string name, int age) {
this ->name = name;
this ->age = age;
return *this ;
}
void printInfo () const {
cout << "Name: " << name << ", Age: " << age << endl;
}
};
int main () {
Person p ("Alice" , 30 ) ;
p.printInfo ();
p.setAge (31 ).setName ("Bob" ).printInfo ();
Person p2 ("Charlie" , 25 ) ;
p2. setInfo ("David" , 26 ).printInfo ();
return 0 ;
}
当构造函数的参数名与成员变量名相同时,必须使用 this-> 来明确指定是对对象成员的赋值。
链式调用(返回 *this):
通过返回当前对象的引用,可以实现连续调用多个方法,如:
p.setAge (31 ).setName ("Bob" ).printInfo ();
printInfo 被声明为 const 方法:表示该方法不会修改对象的状态,
用途 示例 区分成员变量与参数 this->name = name; 实现链式调用 return *this; 传递当前对象 someFunction(this);
new 关键字 在 C++ 中,new 关键字用于动态分配内存。它是 C++ 中处理动态内存分配的主要工具之一,允许程序运行时根据需要分配内存。
使用 new 可以在堆上动态分配一个对象。例如,new int 会分配一个 int 类型的空间,并返回指向该空间的指针
int * p = new int ;
int * q = new int (10 );
new 也可以用来分配一个对象数组。例如,new int[10] 会分配一个包含 10 个整数的数组。
MyClass* obj = new MyClass ();
可以在 new 表达式中使用初始化。用于单个对象,可以使用构造函数的参数。
MyClass* obj = new MyClass (arg1,arg2);
与 delete 配对使用 使用 new 分配的内存必须显式地通过 delete(对于单个对象)或 delete[](对于数组)来释放,以避免内存泄露:
#include <iostream>
#include <new>
class MyClass {
public :
MyClass () {
std::cout << "MyClass created\n" ;
}
~MyClass () {
std::cout << "MyClass destroyed\n" ;
}
void print () {
std::cout << "Hello from MyClass!\n" ;
}
};
int main () {
MyClass* obj1 = new MyClass ();
obj1->print ();
delete obj1;
MyClass* objArray = new MyClass[3 ];
delete [] objArray;
int * largeArray = new (std::nothrow) int [1000000000 ];
if (largeArray) {
std::cout << "Allocation succeeded!\n" ;
delete [] largeArray;
} else {
std::cerr << "Allocation failed!\n" ;
}
int * leaky = new int (42 );
return 0 ;
}
十一、析构函数 析构函数是 C++ 中的一个特殊的成员函数,他在 4 对象生命周期结束时被自动调用,用于执行对象销毁前的清理工作。其十分重要,尤其是在涉及动态分配的资源(如内存、文件句柄、网络连接等)的情况下。
名称:析构函数的名称由波浪号(~)后跟类名组成,如 ~Myclass()。
无返回值和参数:析构函数不接受任何参数,也不返回任何值。
自动调用:当对象的生命周期结束时(例如,一个局部对象的作用域结束,或者使用 delete 删除一个动态分配的对象),析构函数会被自动调用。
不可重载:每一个类只能有一个析构函数。
继承和多态:如果一个类是多态基类,其析构函数应该是虚的。
class 类名 {
public :
~类名();
};
类名::~类名() {
}
十二、静态成员 静态成员在 C++ 类中是一个重要的概念,它包括静态成员变量和静态成员函数。
定义:静态成员变量是类的所有对象共享的变量。与普通成员变量相比,无论创建了多少个类的实例,静态成员变量只有一份拷贝。
初始化: