使用 new 和 delete 在宏中实现 C realloc
Implementing C realloc in a macro with new and delete
我正在使用一个库,它可以让我重写它的一些宏,以了解它如何分配给堆
#define STBI_MALLOC(sz) malloc(sz)
#define STBI_REALLOC(p,newsz) realloc(p,newsz)
#define STBI_FREE(p) free(p)
我想接受其中一些已分配的堆到我的程序中,而不用包装它或过分担心它是如何分配的,方法是使 STBI_FREE()
宏与我通常如何释放此类内存的方式同义, delete [](char*)p
#define STBI_MALLOC(sz) ((void*)new char[sz])
#define STBI_REALLOC(p,newsz) ???
#define STBI_FREE(p) (delete [](char*)(p))
不过,我不确定 STBI_REALLOC()
使用什么。如果我有以前的尺寸,我可以在多行中完成,但是...
// STBI_REALLOC(p,newsz)
if (newsz <= ???) { // don't know the allocation size
return p;
} else {
char * next = new char[newsz]
memcpy(next, p, ???); // don't know the allocaion size
delete [] (char*)p;
return (void*)next;
}
...在本质上不知道分配的大小的情况下,宏在库中接受的参数是不可能的。我在这里有一个选项可以插入这个宏定义吗?
--- 编辑 ---
(已接受的答案仍然有效,这超出了原始问题的范围,但我将其附加以防使用相同库的任何人遇到它)
原来这个库有一个隐藏的预处理器部分用于这个确切的场景,如果它是由库用户定义的,库将改为使用 STBI_REALLOC_SIZED(p,oldsz,newsz)
。
这让我可以为图书馆定义以下绝对杰作:
#define STBI_MALLOC(sz) ((void*)(new char[sz]))
#define STBI_REALLOC_SIZED(p,oldsz,newsz) \
((newsz) <= (oldsz) ? (void*)(p) : [](void* lp, size_t loldsz, size_t lnewsz)->void*{char*n = new char[lnewsz]; memcpy(n, lp, loldsz); delete [] (char*)lp; return (void*)n;}(p, oldsz, newsz))
#define STBI_FREE(p) (delete [](char*)(p))
或者这个也很好用
#define REALLOC_SIZED(p,oldsz,newsz) \
((newsz) <= (oldsz) ? (void*)(p) : \
memcpy(new char[newsz], (void*)std::unique_ptr<char>((char*)(p)).get(), oldsz))
TL;DR - 做不到,代码保持原样。
在 C++ 中没有 realloc
的可能性。 realloc
违背了 C++ 面向对象的本质,因为对象不能像那样移动,所以 C++ 完全否定了这个想法。
也不能用 new
和 delete
来实现,因为你需要知道当前数组大小才能复制数据,这是不可能的(以可移植的方式),不是更不用说每次都必须复制东西是低效的(realloc
在许多情况下就地工作)。
好消息是,在 C++ 程序中使用 malloc
、realloc
和 free
分配原始内存没有任何问题。此外,内置 new
和 delete
在许多情况下委托给 malloc
和 free
,因此实际上没有问题。
我正在使用一个库,它可以让我重写它的一些宏,以了解它如何分配给堆
#define STBI_MALLOC(sz) malloc(sz)
#define STBI_REALLOC(p,newsz) realloc(p,newsz)
#define STBI_FREE(p) free(p)
我想接受其中一些已分配的堆到我的程序中,而不用包装它或过分担心它是如何分配的,方法是使 STBI_FREE()
宏与我通常如何释放此类内存的方式同义, delete [](char*)p
#define STBI_MALLOC(sz) ((void*)new char[sz])
#define STBI_REALLOC(p,newsz) ???
#define STBI_FREE(p) (delete [](char*)(p))
不过,我不确定 STBI_REALLOC()
使用什么。如果我有以前的尺寸,我可以在多行中完成,但是...
// STBI_REALLOC(p,newsz)
if (newsz <= ???) { // don't know the allocation size
return p;
} else {
char * next = new char[newsz]
memcpy(next, p, ???); // don't know the allocaion size
delete [] (char*)p;
return (void*)next;
}
...在本质上不知道分配的大小的情况下,宏在库中接受的参数是不可能的。我在这里有一个选项可以插入这个宏定义吗?
--- 编辑 ---
(已接受的答案仍然有效,这超出了原始问题的范围,但我将其附加以防使用相同库的任何人遇到它)
原来这个库有一个隐藏的预处理器部分用于这个确切的场景,如果它是由库用户定义的,库将改为使用 STBI_REALLOC_SIZED(p,oldsz,newsz)
。
这让我可以为图书馆定义以下绝对杰作:
#define STBI_MALLOC(sz) ((void*)(new char[sz]))
#define STBI_REALLOC_SIZED(p,oldsz,newsz) \
((newsz) <= (oldsz) ? (void*)(p) : [](void* lp, size_t loldsz, size_t lnewsz)->void*{char*n = new char[lnewsz]; memcpy(n, lp, loldsz); delete [] (char*)lp; return (void*)n;}(p, oldsz, newsz))
#define STBI_FREE(p) (delete [](char*)(p))
或者这个也很好用
#define REALLOC_SIZED(p,oldsz,newsz) \
((newsz) <= (oldsz) ? (void*)(p) : \
memcpy(new char[newsz], (void*)std::unique_ptr<char>((char*)(p)).get(), oldsz))
TL;DR - 做不到,代码保持原样。
在 C++ 中没有 realloc
的可能性。 realloc
违背了 C++ 面向对象的本质,因为对象不能像那样移动,所以 C++ 完全否定了这个想法。
也不能用 new
和 delete
来实现,因为你需要知道当前数组大小才能复制数据,这是不可能的(以可移植的方式),不是更不用说每次都必须复制东西是低效的(realloc
在许多情况下就地工作)。
好消息是,在 C++ 程序中使用 malloc
、realloc
和 free
分配原始内存没有任何问题。此外,内置 new
和 delete
在许多情况下委托给 malloc
和 free
,因此实际上没有问题。