c++入门基础—new与delete以及c++11的新特性(auto,范围for)
这里写自定义目录标题
一、new/delete
1.c语言中的动态内存申请
malloc()
核心功能:向系统堆内存申请一块连续的、大小为size字节的内存块
返回值:
成功:返回指向该内存块的void*指针(需强制转换为实际类型)
失败:返回NULL(内存不足时)
内存状态:分配的内存未经初始化,保留之前的内存残留值(随机数据)
calloc()
核心功能:分配nmemb个大小为size的元素内存,且自动初始化为 0
与malloc的区别:
参数形式:calloc(n, size) 等价于 malloc(n*size) + memset(0)
初始化:calloc确保内存全为 0,malloc不初始化
realloc()
核心功能:调整已分配内存块的大小(扩大或缩小)
关键特性:
若原内存块后有足够空间,直接扩展(原地扩容)
若空间不足,分配新内存块并复制原数据,释放旧块(迁移扩容)
返回值:
成功:返回新内存块地址(可能与原地址不同)
失败:返回NULL(原内存块仍有效)
free()函数
作用:将动态分配的内存归还给系统,供其他程序使用
注意事项:
只能释放堆内存(不能释放栈内存,如局部变量)
不能重复释放(会导致 “double free” 错误,程序崩溃)
释放后指针仍指向原地址(成为野指针),需置为NULL
2.c++中的动态内存申请
2.1new的运算符的使用``
int main()
{
int n = 10;
int* ipa = new int(10);
//这个【n】代表的是申请n个连续的int空间大小,并将这块空间初始化为10,这里的n可以是常量也可以是变量。
int* ipb = new int[n](10);
int* ipc = new int[n] {1, 2, 3, 4, 5, 6, 7};
delete ipa;
delete[] ipb;
delete[] ipc;
return 0;
}
new申请内存空间分为三步:
①自动计算申请的内存空间大小;
②使用malloc申请这块空间;
③初始化()里的值就是初始化申请内存空间的值)
2.2new的函数方式的使用
2.3定位new
2.3.1 定位new的定义
定位 new(Placement new)是 C++ 中 new 运算符的一种特殊用法,允许在预先分配的内存空间上直接构造对象,无需额外分配内存。
作用
普通 new 操作符会执行两个步骤:首先分配内存,然后在分配的内存上构造对象。定位 new 则跳过了内存分配步骤,直接在现有内存上构造对象。这种特性适用于以下场景:
- 内存池技术:预先分配大块内存(内存池),需要创建对象时从池中取出合适内存块,使用定位 new 构造对象,避免频繁内存分配和释放带来的性能损耗。
- 硬件相关编程:当需要在特定内存地址(如硬件设备的内存映射地址)上构造对象时,可先获取该地址指针,再通过定位 new 构造对象。
#include <iostream>
class MyClass {
public:
MyClass(int val) : value(val) {
std::cout << "构造函数调用,值为:" << value << std::endl;
}
~MyClass() {
std::cout << "析构函数调用,值为:" << value << std::endl;
}
int value;
};
int main() {
// 分配一块足够大的内存来容纳 MyClass 对象
void* mem = operator new(sizeof(MyClass));
// 使用定位 new 在 mem 指向的内存上构造 MyClass 对象
MyClass* obj = new (mem) MyClass(10);
std::cout << "对象的值:" << obj->value << std::endl;
// 手动调用析构函数,因为定位 new 不会自动调用析构函数
obj->~MyClass();
// 释放之前分配的内存
operator delete(mem);
return 0;
}
定位new其实就是相当于你在已经申请好的内存上构造对象,利用已有的内存空间进行构造,例如:double dx=12.25 new(&dx)char [7]{“yhping”
3.new和malloc区别
1、new/delete 是 C++ 中的运算符。malloc /free 是函数 api。
2、malloc 申请内存空间时,手动计算所需大小,new 只需类型名,自动计算大小;
3、malloc 申请的内存空间不会初始化,new 可以初始化;
4、malloc 的返回值为 void*, 接收时必须强转,new 不需要;
5、malloc 申请内存空间失败时,返回的是 NULL,使用时必须判空;
6、new 申请内存空间失败时抛出异常,所以要有捕获异常处理程序
int main()
{
auto x = 5;
const auto* xp = &x, u;
const auto* sp = &x, z = 6.0;
}
这段代码中,第一个可以执行通过:auto推导为int;
第二个不可以:首先对于const autoxp=&x;我们可以推导出auto为int,但是此时的const autou;他并没有初始化,所以无法推导auto类型
第三个也不可以:因为const auto *sp=&x,我们可以推出来auto是int,但是const auto *z=6.0,推导出auto是double,这就存在了二异性。

4.free和delete的区别
- 所属范畴
free 是 C 语言标准库中的函数,定义在 (或 <stdlib.h>)头文件中,是 C 语言进行动态内存管理的工具。
delete 是 C++ 中的运算符,是 C++ 为了更好地支持面向对象编程(特别是处理对象的构造和析构)而提供的内存释放机制。 - 操作对象
free 仅能释放由 malloc、calloc、realloc 等 C 语言内存分配函数所分配的内存。它只是简单地将内存归还给系统,不会对内存中的对象做任何额外操作
delete 主要用于释放由 new 分配的内存。对于简单数据类型(如 int、char 等),delete 类似 free,只是释放内存;但对于类对象,delete 会先调用对象的析构函数,完成对象相关资源(如动态成员变量、打开的文件等)的清理,然后再释放对象占用的内存。
3.内存分配与释放的匹配
为了避免内存问题,内存分配和释放必须严格匹配:
由 malloc 分配的内存,必须用 free 释放。
由 new 分配的单个对象内存,必须用 delete 释放。
由 new[] 分配的数组内存,必须用 delete[] 释放。
4.需要特别注意的是:用new申请的动态内存,在通过delete释放后,绝对不能再对原指针进行解引用,这种操作属于严重的未定义行为。
具体原理是:delete的核心作用是将new申请的内存区域 “归还操作系统”,让这部分内存重新进入 “可分配内存池”,供其他程序或代码复用。但delete本身不会修改原指针的指向—— 指针变量存储的 “内存地址值” 依然是原来的数值,只是这个地址对应的内存空间,其 “使用权已不属于当前程序”。
此时的指针被称为 “野指针”(或 “悬挂指针”):它看似有明确指向,实则指向的是 “已失效的内存”。若强行解引用,可能会读取到垃圾数据、篡改其他程序的内存(引发程序崩溃),甚至导致更隐蔽的逻辑错误,且错误结果完全无法预测。
二、auto
1.auto类型推导
auto定义的变量,可以根据初始化的值,在编译的过程中推导出变量名的类型。示例:
// 上方代码
int main()
{
auto x = 5; // 使用auto自动推导x为int类型
auto pi = new auto(1); // 使用auto自动推导pi为int*类型(指向动态分配的int)
const auto *xp = &x, u = 6; // xp为const int*类型,u为const int类型
static auto dx = 0.0; // 静态变量dx,auto推导为double类型
auto int b; // C++11前的旧语法,等同于int b(现代C++中不推荐使用)
auto s ; // 错误:auto无法推导未初始化变量的类型
}
// 下方练习代码
int main()
{
auto x = 5; // x被推导为int类型
const auto *xp = &x, u; // err0r:xp为const int*类型,u为const int类型(未初始化)
const auto *ip = &x, u = 6.0;// error;ip为const int*类型,u为const double类型
return 0;
}
2.auto的限制
1.auto无法定义数组
2.auto不能作为函数参数
3.auto不能用于非静态成员变量
4.实例化模板不能使用auto作为模板参数
3.auto可以推导函数的返回类型
更多推荐



所有评论(0)