c++杂记(new)
2013-05-03 13:50
99 查看
这些东西是平时遇到的, 觉得有一定的价值, 所以记录下来, 以后遇到类似的问题可以查阅, 同时分享出来也能方便需要的人, 转载请注明来自RingOfTheC[ring.of.the.c@gmail.com]
1. new
前提知识: 区分new和new操作符
new 的过程 1. 调用new操作符获取内存
2. 在内存上执行构造函数
其中, 第一步new操作符可以重载
a. c++中, new失败默认是抛出异常, 所以检查new返回的指针是否为NULL是没有意义的
char* p = new char[12];
if (p == NULL) // 没意义, 如果new失败, 根本就不会走到这里来
/* ….. */
正确的检查办法是:
try{ char *p = new char[12]; /* …….. */ }
catch(const bad_alloc& e) {/* ………. */}
b. 如果想让new失败返回NULL指针而不抛异常, 可以使用nothrow方法,
char* p = new (std::nothrow) char[12];
if (p == NULL) // 这下就是预期行为了, new失败了, 只是返回NULL指针
/* …… */
c. 在给定的内存上构造一个对象的方法, 注意四点:
void* p = malloc(sizeof(T)); // 1. 自己手动分配内存, 当然可以不是堆上, 可以是栈上等
if (p == NULL)
reuturn ;
T* tp = new(p) T; // 2. 显示调用构造函数
/* 使用 */
tp->~T(); // 3. 必须显示调用析构函数
free(tp); // 4. 释放内存, 如果需要的话
d. 重载类的operator new时, 有一些比较灵活的做法, 你可以向operator new传递你想要的任何参数
1. struct T{
T* operator new(size_t size, size_t extern){
return ::malloc(size + extern);
}
}
T* p = new(15) T; // 这样调用, 上面的size = sizeof(T) , extern = 15
2. struct T{
T* operator new(size_t size, size_t extern, char* log){
return ::malloc(size + extern);
}
}
T* p = new(15, “hi , alloc”) T; // 这样调用, 上面的size = sizeof(T), extern = 15, log = "hi , alloc"
从上面可以看出, 重载operator new的时候, 函数的第一个参数固定不变的是重载了new操作符的对象的大小, 除了这个参数, 其它可以自定义:), 这个很灵活
2. delete没有new那么多的魔法
除了正常的delete, 类的重载operator delete可以有 operator delete(void* p)和operator delete(void* p, size_t size)两个形式, 其中size是该类的size大小, 借此可以证明 "delete一个父类指针, 但这个指针实际上是指向其子类的造成内存回收问题"
struct T{
int a;int b;
void* operator new(size_t size) { return ::operator new(size); }
void operator delete(void* p, size_t size) { ::operator delete(p); }
}
struct D : T{
int c;
}
测试程序:
T* p = new D; // 这里跟进去operator new参数是12 及sizeof(D)
delete T; // 这里跟入去会发现operator delete的第二参数是8及sizeof(T), 明显内存泄露了, 所以大家一再强调, 做父类的最好把自己定义一个虚的析构函数, 修改后如下:
struct T{
int a;int b;
void* operator new(size_t size) { return ::operator new(size); }
void operator delete(void* p, size_t size) { ::operator delete(p); }
virtual ~T(){}
}
struct D : T{
int c;
}
测试程序:
T* p = new D; // 这里跟进去operator new参数是12 及sizeof(D)
delete T; // 这里跟入去会发现operator delete的第二参数是8及sizeof(D), 是我们想要的
好了, 举这个例子不是为了说明父类和子类这些内存问题, 而是为了说明, delete有这样一个参数, 而且这个参数很有用, 很能说明问题, 可以用来检测错误, log统计等.
1. new
前提知识: 区分new和new操作符
new 的过程 1. 调用new操作符获取内存
2. 在内存上执行构造函数
其中, 第一步new操作符可以重载
a. c++中, new失败默认是抛出异常, 所以检查new返回的指针是否为NULL是没有意义的
char* p = new char[12];
if (p == NULL) // 没意义, 如果new失败, 根本就不会走到这里来
/* ….. */
正确的检查办法是:
try{ char *p = new char[12]; /* …….. */ }
catch(const bad_alloc& e) {/* ………. */}
b. 如果想让new失败返回NULL指针而不抛异常, 可以使用nothrow方法,
char* p = new (std::nothrow) char[12];
if (p == NULL) // 这下就是预期行为了, new失败了, 只是返回NULL指针
/* …… */
c. 在给定的内存上构造一个对象的方法, 注意四点:
void* p = malloc(sizeof(T)); // 1. 自己手动分配内存, 当然可以不是堆上, 可以是栈上等
if (p == NULL)
reuturn ;
T* tp = new(p) T; // 2. 显示调用构造函数
/* 使用 */
tp->~T(); // 3. 必须显示调用析构函数
free(tp); // 4. 释放内存, 如果需要的话
d. 重载类的operator new时, 有一些比较灵活的做法, 你可以向operator new传递你想要的任何参数
1. struct T{
T* operator new(size_t size, size_t extern){
return ::malloc(size + extern);
}
}
T* p = new(15) T; // 这样调用, 上面的size = sizeof(T) , extern = 15
2. struct T{
T* operator new(size_t size, size_t extern, char* log){
return ::malloc(size + extern);
}
}
T* p = new(15, “hi , alloc”) T; // 这样调用, 上面的size = sizeof(T), extern = 15, log = "hi , alloc"
从上面可以看出, 重载operator new的时候, 函数的第一个参数固定不变的是重载了new操作符的对象的大小, 除了这个参数, 其它可以自定义:), 这个很灵活
2. delete没有new那么多的魔法
除了正常的delete, 类的重载operator delete可以有 operator delete(void* p)和operator delete(void* p, size_t size)两个形式, 其中size是该类的size大小, 借此可以证明 "delete一个父类指针, 但这个指针实际上是指向其子类的造成内存回收问题"
struct T{
int a;int b;
void* operator new(size_t size) { return ::operator new(size); }
void operator delete(void* p, size_t size) { ::operator delete(p); }
}
struct D : T{
int c;
}
测试程序:
T* p = new D; // 这里跟进去operator new参数是12 及sizeof(D)
delete T; // 这里跟入去会发现operator delete的第二参数是8及sizeof(T), 明显内存泄露了, 所以大家一再强调, 做父类的最好把自己定义一个虚的析构函数, 修改后如下:
struct T{
int a;int b;
void* operator new(size_t size) { return ::operator new(size); }
void operator delete(void* p, size_t size) { ::operator delete(p); }
virtual ~T(){}
}
struct D : T{
int c;
}
测试程序:
T* p = new D; // 这里跟进去operator new参数是12 及sizeof(D)
delete T; // 这里跟入去会发现operator delete的第二参数是8及sizeof(D), 是我们想要的
好了, 举这个例子不是为了说明父类和子类这些内存问题, 而是为了说明, delete有这样一个参数, 而且这个参数很有用, 很能说明问题, 可以用来检测错误, log统计等.
相关文章推荐
- c++杂记(new)
- 详解c++中的new跟delete
- C++中关于函数内静态数组和new分配的动态数组的区别分析
- C++学习day5之new_and_delete
- 深入浅析C++的new和delete
- C++基础学习笔记----第十四课(new和malloc的区别、单例模式等深入)
- 【小记备忘】之C/C++ 杂记,catch,调用构造函数,内存分配,隐式转换【2013.12.11】
- C++基础入门教程(五):new和delete
- C++ 内存分配(new,operator new)详解
- C++在堆上申请和释放内存 - new & delete
- C++基础--malloc和new的区别
- C++程序运行时内存布局之----------局部变量,全局变量,静态变量,函数代码,new出来的变量
- NEW IN C++ 11
- new, newlc and new in C++
- c++ : new 在特定指针处构造初始化
- VS2005 C++ 手机开发杂记(下)
- c++中new和delete的使用方法
- C++基础杂记
- C++标准转换运算符 :reinterpret_cast <new_type> (expression)
- C++用new和不用new创建类对象区别