动态内存的相关问题
● sizeof 不会返回动态分配的内存大小
#include<iostream>
#include<new>
#include<memory>
#include<vector>
int main(int argc, char *argv[])
{
int* ptr = new int(3);
std::cout << sizeof(ptr) << std::endl; //返回的是int*的尺寸而非ptr指向的内存的尺寸
std::vector<int> x;
x.push_back(10);
x.push_back(10);
x.push_back(10);
x.push_back(10);
x.push_back(10); //push_back只影响x中指向的内存(运行期)的大小,而不会影响x(编译期)本身的大小
std::cout << sizeof(x) << std::endl; //x中包含指向的内存的指针和其他的一些信息,因此在此系统上返回16个字节
return 0;
}
● 使用分配器( allocator )来分配内存
#include<iostream>
#include<new>
#include<memory>
#include<vector>
int main(int argc, char *argv[])
{
std::allocator<int> al;
int* ptr = al.allocate(3); //只分配(不初始化)一块含有3个int类型的内存
al.deallocate(ptr, 3); //这里的3要和al.allocate(3);中的3相同,即分配多少内存,释放多少内存,否则行为是未定义的
std::allocator<int> al2;
al2.allocate(5); //没有指定一个变量将它保存下来
return 0;
}
● 使用 malloc / free 来管理内存
C语言并不强调对象的构造,在C++引入类之后,类的构造函数和析构函数刻画出了对象在构造时和销毁时的行为,这才强调了对象的构造。
malloc / free缺点是不能对齐内存
● 使用 aligned_alloc 来分配对齐内存
Since C11(注意这是C语言的标准)
● 动态内存与异常安全
#include<iostream>
#include<new>
#include<memory>
#include<vector>
void fun()
{
int* ptr = new int(3);
//... //如果这里产生了异常,那么就不会执行delete ptr;,造成内存泄漏,称为不是异常安全的
delete ptr;
}
int main(int argc, char *argv[])
{
//... //多次调用f()
int* ptr = new int(3);
//... //即使这里产生了异常,由于main()在线程中执行,main()结束线程里的所有资源都会被系统释放,因此不会泄漏内存,称为异常(不是特别安全的,而是产生了异常仍能保证安全)安全的
delete ptr;
return 0;
}
#include<iostream>
#include<new>
#include<memory>
#include<vector>
void fun()
{
std::shared_ptr<int> ptr(new int(3));
//... //异常安全的
}
int main(int argc, char *argv[])
{
//... //多次调用f()
return 0;
}
● C++ 对于垃圾回收的支持
垃圾回收会耗费系统资源,降低程序性能
对象生命周期的精确控制
因此C++并不热衷垃圾回收的支持
参考
深蓝学院:C++基础与深度解析