C++ 的内存分配方式和c有区别,c采用的是malloc realloc calloc 等方式,c++采用new和delete
首先要明白堆栈的概念
全局区,静态区:static
常量区: ""
堆:new,【需要自己主动释放】
栈:局部变量,【最大空间以系统为准,一般2M,超过会抛Stack Overflow的错误】
c++中声明对象的方式有如下几种
T t;
T t();
T* t= new T(); //new 会在堆开辟一个空间
实例:
#include <iostream>
class T {
public :
T(){
std::cout<<"构造函数"<<count<<std::endl;
}
~T(){
std::cout<<"析构函数"<<count<<std::endl;
}
T(const T& t){
std::cout<< "拷贝构造函数"<<count<<std::endl;
}
T& operator= (const T &t){
std::cout<< "赋值操作符"<<count<<std::endl;
}
void countPP(){
count ++;
}
void printData(){
std::cout<< "我是打印"<<count<<std::endl;
}
private:
int count =0;
};
void fun(T * t){
t->countPP();
t->printData();
std::cout<<"执行完毕"<<std::endl;
}
int main(int argc, char *argv[])
{
T t ; //栈上,不需要自己释放
fun(&t);
std::cout<<"执行第二种申请方式"<<std::endl;
T* tp = new T();//在堆上,需要自己释放
fun(tp);
delete tp;
tp= NULL; // 需要指向NULL,否则有可能误触不可访问的内存地址
}
输出
构造函数0
我是打印1
执行完毕
执行第二种申请方式
构造函数0
我是打印1
执行完毕
析构函数1 【这个是指针的释放,由我们调用delete触发】
析构函数1 【方法退出,由系统自动调用析构】
由上面可以看出在调用完毕相应的方法之后,需要主动释放。
所有的程序都是由简到繁,所以注重释放的时机很重要
原则上,谁申请谁消费的原则。
这里再举一个例子,来说明你是否明白了堆栈的概念。【可能会有点绕】
//KTmpCommSession.h
class KTmpCommSession
{
public:
KTmpCommSession();
static uint32_t& get_session_id();
};
//KTmpCommSession.cpp
KTmpCommSession::KTmpCommSession()
{
}
static uint32_t session_id = 0;
uint32_t &KTmpCommSession::get_session_id()
{
return session_id;
}
//ktmp.h
template <typename T>
class KTmp:public KTmpCommSession
{
public:
KTmp(){autoIncreateSessionId();}
public:
T* callback = nullptr;
int getSessionId()
{
return get_session_id();
}
private:
void autoIncreateSessionId()
{
++get_session_id();
if(get_session_id() == 0)
{
get_session_id() = 1;
}
}
};
首先定义了一个模板类,细心的同学是不是发现为什么要对一个模板类进行继承,原因:是因为我想我的所有模板都有一个共有的属性,而这个属性每次在构造的时候都会被累加。每构造一个不同的模板子类都会触发这个属性变化。故有了上面的写法。为什么不写在同一个类里面,因为打包的时候可能会因为在不同的so中导致,有bug。
//init.cpp
#include <functional>
typedef std::function<void* (void *)> TEST;
void KInit::active(TEST fun)
{
KTmp<TEST> *args = new KTmp<TEST>();
args->callback = new TEST(fun);//【1】这里注意
async_request(args);//异步发起请求,涉及异步【2】这里注意
}
//args 这个参数是async_request传递过来的参数,这个方法会被async_request调用,async_request的具体实现,这里先不给出,
static void _result_init(void *args){
KTmp<TEST> * param = (KTmp<TEST> *)args;
if(args!=NULL){
TEST * t = param->callback;
(*t)((void*)("")); //【3】这里注意
std::cout<<":::::::void::::"<<t<<std::endl;
}
}
//main.cpp
void * xxx(void * data){
std::cout<<"init init init:"<<std::endl;
}
int main(int argc, char *argv[])
{
KInit init;
init.active(xxx);
}
注意上面标注的【1】【2】【3】
如果【1】没有new的话,那么在【3】就会抛异常,原因就是因为【2】是异步导致被释放了。
参考资料: