是否可以重载new
运算符,以便不创建对象,而是返回现有对象。
如果可以的话,你怎么能在第一时间创建对象:D
这听起来很奇怪我知道。我试图隐藏客户端的一些细节。我在PS2上制作游戏,我想要New Foo()
语法,但想要一个可以替代使用的预制对象列表。
当新操作符返回指向可用内存的指针时,我看不到这种情况。
new Foo;
struct Foo
{
void* operator new(std::size_t)
{
// return pre made obj.
}
};
答案 0 :(得分:6)
据我所知,你无法改变 new 的这个方面,它实际构建了对象。重载运算符只返回原始内存,然后该语言在此内存中自动构造对象。你无法控制这一步。
无论如何,如果你没有得到 new 对象,该语法的重点是什么?
答案 1 :(得分:4)
http://www.cplusplus.com/reference/std/new/operator%20new%5B%5D/
应该告诉你所有你需要知道的事情!
或者甚至是这个
http://www.cplusplus.com/reference/std/new/operator%20new/
operator new是一个可以覆盖的全局函数。
如果您向操作员提供新的操作,请不要忘记您还需要提供操作员删除。
我猜你正试图建立一个内存池,记得实际测量和不测量性能,因为它并不总是值得麻烦恕我直言。
修改强> 在你的问题和其他一些答案之间进行阅读,我的猜测是你真的想要单独重载new / delete和singleton模式。而是采用工厂模式方法。
您的所有代码都会调用
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
}
答案 2 :(得分:2)
您可以重载operator new
,但重载的运算符不会返回一个对象。它返回一个对象的内存,实现安排调用构造函数。
所以你不能做你想做的事。
相反,如果您试图避免的成本是内存分配的成本,那么您的重载可以从预先分配的块中分配一些内存。显然,你负责跟踪什么是免费的,什么不是,你的挑战是比PS2 devkit附带的分配器更有效地做到这一点。这可能不会太难 - 如果你只处理一个类而假设没有人从它那里得到,你就会有不公平的优势,分配的大小是固定的。
如果您要避免的成本是调用构造函数,那么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;
}
}
答案 3 :(得分:1)
如果您想要单个对象,可以使用Singleton pattern。 如果您想要多个对象,则需要object pool。
答案 4 :(得分:1)
重载new
为fraught with peril。它不仅仅是C ++的malloc
,它还具有对象生命周期和异常安全等重要语义。
当你调用new
时,会调用构造函数。你不想两次构造一个对象,因为你不能明智地破坏它两次。充其量你会泄漏资源。
你可能想要的不仅仅是单身,也许可以尝试这样的事情:
foo.h中
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;
}
很多可能性。
答案 5 :(得分:0)
你不仅不能修改operator new
来做你想做的事(它只是一个分配函数),你不应该这样做。颠覆新表达式的含义会使您的代码更难理解,完全没有任何好处。
如果你想要全新的功能,那就写代码吧!在这里,你需要的可能是一个类(我们无法分辨),或者只是一个函数:
template<typename T, typename... U>
std::shared_ptr<T> // for one std::shared_ptr seems appropriate
make(U&&... u);
然后,客户端代码使用此类工厂函数来获取所需的对象。 实际的功能是什么?它是否使用Flyweight模式缓存对象?它是否缓存内存而不是对象?客户端代码不关心,不想。所有它关心的是它获得它要求的对象。
同时,函数中的代码可以执行任何需要的操作。如果明天你意识到你弄错了,你可以改变里面的代码,希望它不会影响其余部分。至少它有一个战斗的机会。
答案 6 :(得分:0)
答案 7 :(得分:0)
使用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++];
}
}