重载new操作符
Overloading the new operator
是否有可能重载new
操作符,从而不创建对象,而是返回一个已存在的对象?
如果这是可能的,你怎么能首先创建对象:D
我知道这听起来很奇怪。我想对客户隐瞒一些细节。我正在PS2上制作一款游戏,我想拥有New Foo()
语法,但想要一个可以使用的预制对象列表。
我不认为可以规避这个问题,因为new操作符返回一个指向可用内存的指针。
new Foo;
struct Foo
{
void* operator new(std::size_t)
{
// return pre made obj.
}
};
据我所知,你不能改变new的这一方面,它实际上构造了对象。重载操作符只返回原始内存,然后语言在该内存中自动构造对象。你不能控制这一步。
无论如何,如果你没有得到一个new对象,那么语法的意义是什么呢?http://www.cplusplus.com/reference/std/new/operator%20new%5B%5D/
应该告诉你所有你需要知道的!
或者这个
http://www.cplusplus.com/reference/std/new/operator%20new/operator new是一个可以覆盖的全局函数。
不要忘记,如果你提供了operator new,你还需要提供operator delete。
我猜你正在尝试设置一个内存池,记住实际测量性能有和没有,因为它并不总是值得的麻烦。
编辑:从你的问题和其他一些答案的字里行间看出来,我猜你真的想让重载new/delete和单例模式单独存在。相反,应该采用工厂模式方法。
你所有的代码都调用
SomethingStatic: GetNewWhatsit ()
函数(而不是构造对象)它返回数组中的下一个指针。指向对象的指针数组,这些对象是在程序初始化时以常规方式创建的。
whatsit* GetNewWhatsit()
{
if (num_of_objects > ARRAY_SIZE(whatsit_cache))
return 0;
else
return whatsit_cache[num_of_objects++]; // post inc. on purpose
}
您可以重载operator new
,但是重载的操作符不返回对象。它返回对象的内存,并安排调用构造函数。
所以你不能做你想做的事。
相反,如果您试图避免的成本是内存分配的成本,那么您的重载可以从预分配的块中分配一些内存。显然,你要负责跟踪哪些是免费的,哪些不是,你的挑战是比PS2开发工具包附带的分配器更有效地做到这一点。这可能并不太难——如果你只处理一个类,并假设没有人从它派生,那么你就有一个不公平的优势,即分配的大小是固定的。
如果您试图避免调用构造函数的成本,那么operator new
对您没有帮助,但是您可以编写一种包装器:
struct FooWrapper {
Foo *foo;
FooWrapper(): foo(choose_a_pre_existing_foo()) { }
~FooWrapper() {
foo->reset(); // clear up anything that shouldn't be kept
return_to_the_pool_for_reuse(foo);
}
private:
FooWrapper(const FooWrapper &);
FooWrapper &operator=(const FooWrapper &);
};
Foo *choose_a_pre_existing_foo() {
// possibly some kind of synchronization needed if list is global
// and program is multi-threaded.
if list_of_foos.empty() {
return new Foo();
} else {
Foo *f = list_of_foos.back();
list_of_foos.pop_back();
return f;
}
}
超载new
充满危险。它不仅仅是c++的malloc
,它在对象生命周期和异常安全等方面具有重要的语义。
当你调用new
时,构造函数被调用。你不会想要构造一个对象两次,因为你不可能销毁它两次。你最多只能泄漏资源。
您可能想要的不仅仅是单例,也许可以尝试这样做:
foo。
struct Foo {
static Foo instance_a;
static Foo instance_b;
enum Predefined {
ALICE,
BOB
};
static Foo & instance (Predefined);
// ...
}
foo.cpp
Foo Foo :: instance_a (1, 2, 3);
Foo Foo :: instance_b ("alpha");
namespace {
Foo alice;
Foo bob (1, "x");
}
Foo & Foo :: instance (Predefined name) {
// ...
return alice;
}
很多可能性。
如果你想要单个对象,可以使用Singleton模式。如果需要多个对象,则需要一个对象池。
您不仅不能修改operator new
来做您想做的事情(它只是一个分配函数),而且不应该这样做。破坏新表达式的含义会使代码更难理解,没有任何好处。
如果你想要全新的功能,那就写代码吧!在这里,您需要的可能是一个类(我们无法判断),或者可能只是一个函数:
template<typename T, typename... U>
std::shared_ptr<T> // for one std::shared_ptr seems appropriate
make(U&&... u);
客户端代码然后使用这个类似工厂的函数来获取它需要的对象。函数实际上是做什么的?它是否使用Flyweight模式缓存对象?它缓存内存而不是对象吗?客户端代码不在乎,也不想。它所关心的只是获取它所请求的对象。
同时,函数中的代码做它需要做的任何事情。如果明天你意识到你做错了,你可以修改里面的代码,希望它不会影响到其他部分。至少它还有奋斗的机会。
我建议使用桥接模式。
这意味着你的客户端可以在一个普通的公共类上调用new,这个公共类内部会选择构造什么或不构造什么。
包含的类可以是库的私有类
使用operator::new的问题是编译器会在调用new之后自动生成一个操作码来调用构造函数,因此new本身并不负责构造函数。你想要的是一个单例:
struct Foo
{
static Foo& NewObject()
{
static Foo* _foo = new Foo;
return *_foo;
}
}
或某种数组:
struct Foo
{
static Foo& NewObject()
{
static Foo* _foo = new Foo[128];
static int index = 0;
if(index == 128)
index = 0;
return _foo[index++];
}
}
- 在重载的全局new操作符中使用静态对象会导致核心转储运行时错误
- 提升ipc new和delete操作符
- 在c++中使用new操作符动态分配数组
- boost::make_shared没有调用(放置)操作符new
- c++中不使用new操作符的内存泄漏
- c++中new操作符与java中new操作符的区别
- 如何从操作符new或mremap的malloc中获取页对齐内存
- 操作符new在异常后销毁初始化的对象
- 操作符new已在带有库的自定义内存管理器中定义
- 关于操作符new()和操作符delete()的问题
- 操作符new(n)与new unsigned char[n]的位置new
- 如何使用操作符new的unique_ptr
- 操作符new将内存初始化为零
- 如何重载操作符new和delete来跟踪内存
- 在类中使用重载操作符new
- 操作符new在c++中的语法对我来说是新的
- 重写操作符new函数的调用堆栈不完整
- 重载操作符new / allocate大于对象大小
- 将原始操作符new、放置new和标准删除合并是否合法
- 重载操作符new