65,208
社区成员
发帖
与我相关
我的任务
分享void * operator new(size_t);
void * operator new[](size_t);
void operator delete(void*);
void operator delete[](void *);
无关
Test t;//这种方式定义的变量 (对象),
//例如。。。函数内部局部变量,外部变量,静态变量,类的静态成员变量,等等,会自动调用析构函数。
cout << t.getX() << endl;
t.~Test(); //()3这里主动调用,析构函数是错误的,因为 析构函数会自动调用。
void * operator new(size_t);
void * operator new[](size_t);
void operator delete(void*);
void operator delete[](void *);
重定义是为了更有效地利用内存,这么定义是为了定义堆对象,
new 的时候,分配内存会自动调用类的operator new,而不是全局的 operator new
即
A *a =new A;//===> 不重载
相当于这么做
a = ::operator new(sizeof(A));
new (a) A();
重载后
相当于这么做
a = A::operator new(sizeof(A));
new (a) A();//
这是重载和不重载的区别。
其他3个运算符类似。
另外 重载以后 直接调用 ::operator new 分配内存毫无意义
因为还需要显式释放
本来定义operator new就是为了不直接用 ::operator new,结果还是显式使用了 ::operator new
何必多此一举。
#include <iostream>
using namespace std;
class Test{
public:
Test():x(3){cout << "ctor Test() is called!" << endl; }
~Test(){ cout << "dtor ~Test() is called!" << endl; }//(1)
int getX(){ return x; }
private:
int x;
void * operator new(size_t);
void operator delete(void*);//(2)
};
int main(){
Test *ptr = ::new Test(); //输出 3
cout << ptr->getX() << endl;
ptr->~Test(); //(4)
::delete ptr; //(5)
return 0;
}
可是我这样,用全局的new从堆上分配的内存,这样的情况也编译不通过,我做这个小例子本来是想不允许用户在堆上申请内存的,我上面的代码用了全局的::new与全局的::delete结果还是编译不通过,全局的new,delete与类内部的new,delete与析构函数之间有什么联系吗?
如果不重写析构函数上面的代码是可以通过的, 如果不在类中重写operator delete也是可以编译通过的,我不明白其中的关系[/quote]
楼主几个关键概念需要理解:
1,new是一个关键字,它的动作是:void* operator new(size_t) + operator new(size_t,void*ptr),既先分配一块内存,然后在内存上构造对象。
2,所以楼主代码里的::new和::delete是压根不存在的用法。 想要限制一个类在堆上创建是做不到的,虽然你可以private掉static void* operator new(size_t);和static void operator delete(void*);,这样用户调用new和delete会失败,但是用户完全可以显式指定使用::operartor new(size_t)+::operator new(size_t,void*ptr)搞定。[/quote]
版主好,::new ::delete确实是存在的,在c++ primer 中有讲到,我清楚全局的operator new是库函数,而类中重写的是操作符, 如果使用new操作符会先调用库函数operator new然后再调用类的构造函数, delete是先调用析构函数,再调用库函数operator delete。
你看看下面的代码及运行结果
#include <iostream>
using namespace std;
class Test{
public:
Test():x(3){cout << "ctor Test() is called!" << endl; }
int getX(){ return x; }
private:
int x;
void * operator new(size_t);
void operator delete(void*);//(2)
};
int main(){
Test *ptr = ::new Test(); //输出 3
cout << ptr->getX() << endl;
ptr->~Test(); //(4)
::delete ptr; //(5)
cout << "----------------" << endl;
Test *p = static_cast<Test*>(::operator new((size_t)sizeof(Test)));
cout << p->getX() << endl;
::operator delete(p);
return 0;
}
[/quote]
::new和::delete不太了解,如果可以这样的话那的确是封不住用户了,走的全都是全局重载。#include <iostream>
using namespace std;
class Test{
public:
Test():x(3){cout << "ctor Test() is called!" << endl; }
~Test(){ cout << "dtor ~Test() is called!" << endl; }//(1)
int getX(){ return x; }
private:
int x;
void * operator new(size_t);
void operator delete(void*);//(2)
};
int main(){
Test *ptr = ::new Test(); //输出 3
cout << ptr->getX() << endl;
ptr->~Test(); //(4)
::delete ptr; //(5)
return 0;
}#include <iostream>
using namespace std;
class Test{
public:
Test():x(3){cout << "ctor Test() is called!" << endl; }
int getX(){ return x; }
private:
int x;
void * operator new(size_t);
void operator delete(void*);//(2)
};
int main(){
Test *ptr = ::new Test(); //输出 3
cout << ptr->getX() << endl;
ptr->~Test(); //(4)
::delete ptr; //(5)
cout << "----------------" << endl;
Test *p = static_cast<Test*>(::operator new((size_t)sizeof(Test)));
cout << p->getX() << endl;
::operator delete(p);
return 0;
}
#include <iostream>
#include <new>
class Test
{
public:
Test()
{
std::cout << __FUNCTION__ << std::endl;
}
~Test()
{
std::cout << __FUNCTION__ << std::endl;
}
static void* operator new(size_t, void*); // private则彻底无法从堆上分配
private:
static void* operator new(size_t);
static void operator delete(void*);
};
static void* Test::operator new(size_t size, void* ptr)
{
return ptr;
}
int main(int argc, char** argv)
{
Test t;
// 你只能挡住这种用户
// Test* p = new Test;
// delete p;
// 用户可以这样绕过限制
void* ptr = ::operator new(sizeof(Test));
Test* pobj = new (ptr) Test;
pobj->~Test();
::operator delete(ptr);
return 0;
}#include <iostream>
using namespace std;
class Test{
public:
Test():x(3){cout << "ctor Test() is called!" << endl; }
~Test(){ cout << "dtor ~Test() is called!" << endl; }//(1)
int getX(){ return x; }
private:
int x;
void * operator new(size_t);
void operator delete(void*);//(2)
};
int main(){
Test *ptr = ::new Test(); //输出 3
cout << ptr->getX() << endl;
ptr->~Test(); //(4)
::delete ptr; //(5)
return 0;
}
可是我这样,用全局的new从堆上分配的内存,这样的情况也编译不通过,我做这个小例子本来是想不允许用户在堆上申请内存的,我上面的代码用了全局的::new与全局的::delete结果还是编译不通过,全局的new,delete与类内部的new,delete与析构函数之间有什么联系吗?
如果不重写析构函数上面的代码是可以通过的, 如果不在类中重写operator delete也是可以编译通过的,我不明白其中的关系[/quote]
楼主几个关键概念需要理解:
1,new是一个关键字,它的动作是:void* operator new(size_t) + operator new(size_t,void*ptr),既先分配一块内存,然后在内存上构造对象。
2,所以楼主代码里的::new和::delete是压根不存在的用法。 想要限制一个类在堆上创建是做不到的,虽然你可以private掉static void* operator new(size_t);和static void operator delete(void*);,这样用户调用new和delete会失败,但是用户完全可以显式指定使用::operartor new(size_t)+::operator new(size_t,void*ptr)搞定。#include <iostream>
using namespace std;
class Test{
public:
Test():x(3){cout << "ctor Test() is called!" << endl; }
~Test(){ cout << "dtor ~Test() is called!" << endl; }//(1)
int getX(){ return x; }
private:
int x;
void * operator new(size_t);
void operator delete(void*);//(2)
};
int main(){
Test *ptr = ::new Test(); //输出 3
cout << ptr->getX() << endl;
ptr->~Test(); //(4)
::delete ptr; //(5)
return 0;
}
可是我这样,用全局的new从堆上分配的内存,这样的情况也编译不通过,我做这个小例子本来是想不允许用户在堆上申请内存的,我上面的代码用了全局的::new与全局的::delete结果还是编译不通过,全局的new,delete与类内部的new,delete与析构函数之间有什么联系吗?
如果不重写析构函数上面的代码是可以通过的, 如果不在类中重写operator delete也是可以编译通过的,我不明白其中的关系#include <iostream>
using namespace std;
class Test{
public:
Test():x(3){cout << "ctor Test() is called!" << endl; }
~Test(){ cout << "dtor ~Test() is called!" << endl; }//(1)
int getX(){ return x; }
private:
int x;
void * operator new(size_t);
void operator delete(void*);//(2)
};
int main(){
Test t;
cout << t.getX() << endl;
t.~Test(); //()3
Test *ptr = ::new Test(); //输出 3
cout << ptr->getX() << endl;
ptr->~Test(); //(4)
::delete ptr; //(5)
return 0;
}
上述代码中,标有1,2,3,4,5,如果先将4,5两行代码注释掉,编译是不通过的,原因是3,2,1有冲突,我不明白为什么这里会有冲突,如果将2注释掉就可以。
4,5也是这样的问题,如果要想编译通过,要注释掉2, 如果不重新写自己的析构函数,那不注释掉2,有5也可以正常编译
你可以拷贝一下代码编译试一下,我在vs2012下编译的// c or c++.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <typeinfo>
#include <windows.h>
#include <exception>
using namespace std;
class A
{
public:
A(int _i) :i(_i)
{
cout << "ctor A: " << i << endl;
}
~A()
{
cout << "dctor: " << i << endl;
}
int get(){return i;}
protected:
private:
int i;
};
void *operator new(size_t n)
{
cout << "assigned " << n << "bytes" << endl;
return malloc(n);
}
void operator delete(void *p)
{
cout << "free memory" << endl;
free(p);
}
void my_fun()
{
A a1(1);
A *pa2 = new A(2);
delete pa2;
}
int _tmain(int argc, _TCHAR* argv[])
{
my_fun();
system("pause");
return 0;
}
#include <conio.h>
#include <stdio.h>
#include <iostream>
class C
{
public:
/*virtual*/ ~C() {};
void operator delete (void *) {} /*= delete*/;
};
int main(void)
{
C o1;
_getch();
return(0);
}
只要不是抽象类,同时存在没什么不可以。如果是抽象类的话delete重载必须可以访问。
int main(){
Test t;
cout << t.getX() << endl;
cout << "----------------" << endl;
//t.~Test(); //如果析构函数存在编译错误 析构函数与delete不可同时存在为什么
Test *ptr = ::new Test(); //输出 3
cout << ptr->getX() << endl;
//ptr->~Test(); //如果析构函数存在编译错误
//::delete ptr; //如果析构函数存在编译错误
cout << "----------------" << endl;
Test *p = static_cast<Test*>(::operator new((size_t)sizeof(Test)));
cout << p->getX() << endl;
cout << "----------------" << endl;
::operator delete(p);
你的析构函数调用后,下面还用到这个被析构的类变量不是吗?