包头建设工程安全监督站网站,高级网页设计师证书,wordpress 好用插件,文化礼堂建设情况网站目录一、对new的理解1、new做了什么2、new被编译器转为了什么3、operate_new源代码长啥样二、对delete的理解1、delete做了什么2、delete被编译器转为了什么3、operator delete源代码长啥样三、构造函数与析构函数的直接调用参考一、对new的理解
1、new做了什么
C告诉我们告诉我们new的时候会分配一块内存用来放对象分配好之后会调用构造函数。所以说所谓的自动调用其实是被new调用的。 所以总结new做的动作1、分配内存 2、调用构造函数
2、new被编译器转为了什么
以下面语句为例
Complex* pc new Complex(1,2);仿造编译器的流程可以具化为
try{//1、allocatevoid* mem operate_new(sizeof(Complex));//2、cast,将指针转型为Complex*类型指针pc static_castComplex*(mem);//3、construct注意这种写法只有编译器才能使用我们需要避免这种行为pc-Complex::Complex(1,2);
}
catch(std::bad_alloc){//若allocation失败就不执行构造函数
}注意第3点如果想要直接调用ctor可以使用placement new:
new(p)Complex(1,2);3、operate_new源代码长啥样
这里截取的是vc98版本的源代码 可见如果分配内存成功就返回分配到的内存的指针否则陷入while循环中。 什么时候会失败大量耗用内存之后我们需要new一个对象会发现我们调用不到内存了。 这时会使用callnewh函数即调用newhandle函数这是一种自设定的函数。也就是说分配内存失败就会调用你设定的那个函数。我们需要在newhandle函数中释放内存以便调用完newhandle函数后会有内存给malloc分配。 关于函数的第二个参数 nothrow与异常的抛出有关它是不抛异常意思是说operate_new这个函数是保证不抛异常的在新版的C特性中不抛异常的写法有做修改。 它的解释如下 struct std::nothrow_t {}; The struct is used as a function parameter to operator new to indicate that the function should return a null pointer to report an allocation failure, rather than throw an exception. 二、对delete的理解
1、delete做了什么
C告诉我们delete的时候会先调用析构函数然后调用delete函数释放内存。
2、delete被编译器转为了什么
先调用delete函数
Complex* pc new Complex(1,2);
...
delete pc;被编译器转为
pc-~Complex(); //先析构注意这里可以直接调用析构函数
operator delete(pc); //然后释放内存3、operator delete源代码长啥样
也就是直接调用free函数。 总结一下new与delete调用的是operate_new和operator delete。而operate_new调用的是malloc函数operator delete调用的是free函数。
三、构造函数与析构函数的直接调用
先通过指针调用构造函数这里先选择string类因为string在标准库里面是个typedefine本名为basic_string。编译器把第一个string换成了basic_string后面再找string没有找到所以这里会报错。这个并不是真正不能使用构造函数的原因。 例1 string* pstr new string;cout str *pstr endl;//! pstr-string::string(jjhou); //[Error] class std::basic_stringchar has no member named string
//! pstr-~string(); //crash -- 其語法語意都是正確的, crash 只因為上一行被 remark 起來嘛. cout str *pstr endl;例2 可以看到在GCC里面通过指针或者直接调用构造函数是不正确的在VC中条件会放宽。
class A
{
public:int id;A() : id(0) { cout default ctor. this this id id endl; }A(int i) : id(i) { cout ctor. this this id id endl; }~A() { cout dtor. this this id id endl; }
};A* pA new A(1); //ctor. this000307A8 id1cout pA-id endl; //1
//! pA-A::A(3); //in VC6 : ctor. this000307A8 id3//in GCC : [Error] cannot call constructor jj02::A::A directly//! A::A(5); //in VC6 : ctor. this0013FF60 id5// dtor. this0013FF60 //in GCC : [Error] cannot call constructor jj02::A::A directly// [Note] for a function-style cast, remove the redundant ::Acout pA-id endl; //in VC6 : 3//in GCC : 1 delete pA; //dtor. this000307A8 参考 https://www.bilibili.com/video/BV1Kb411B7N8?p7