我的部分代码仍使用malloc
代替new
。原因是因为我害怕使用new
因为它抛出异常,而不是返回NULL
,我可以轻松检查。将new
中的try{}catch(){}
的每次通话都包含在内也看起来不那么好。使用malloc
时我可以if (!new_mem) { /* handle error */ }
。
因此我有一个问题。我可以将智能指针与malloc
一起使用吗?
类似的东西:
SmartPointer<Type> smarty = malloc(sizeof(Type));
像这样。
这可能吗?
谢谢,Boda Cydo。
答案 0 :(得分:34)
如果您使用的是shared_ptr
或unique_ptr
,则可以指定自定义删除工具。例如,
struct free_delete
{
void operator()(void* x) { free(x); }
};
这可以与shared_ptr
一起使用,如下所示:
std::shared_ptr<int> sp((int*)malloc(sizeof(int)), free_delete());
如果您使用unique_ptr
,则删除器是unique_ptr
类型的一部分,因此需要将删除器指定为模板参数:
std::unique_ptr<int, free_delete> up((int*)malloc(sizeof(int)));
但是,在编写C ++时,最好正确使用异常,而不是避免使用异常,尤其是在分配失败方面。在大多数情况下,您无法从尝试进行分配的函数中的分配失败中成功恢复,因此异常可以帮助您处理实际能够处理它的错误。
答案 1 :(得分:9)
您可以对new运算符使用nothrow关键字,它将返回NULL而不是抛出异常。详情见下面的链接: http://www.cplusplus.com/reference/std/new/nothrow/
答案 2 :(得分:3)
最佳解决方案是使用new (std::nothrow) Type
。这将像new Type
一样,但如果失败则会给出null而不是抛出。这比让malloc
表现得像new
更容易。
如果你真的必须使用malloc
,那么请记住正确构造和破坏对象:
void* memory = malloc(sizeof(Type));
Type* object = new (memory) Type;
object->~Type();
free(object); // or free(memory)
您可以通过为自定义删除器提供一些智能指针来使用它:
void malloc_deleter(Type* object)
{
object->~Type();
free(object);
}
if (void* memory = malloc(sizeof(Type)))
{
Type* object = new (memory) Type;
std::shared_ptr<Type> ptr(object, malloc_deleter);
DoStuff(ptr);
}
但是使用非投掷新内容会更简单:
if (Type* object = new (std::nothrow) Type)
{
std::shared_ptr<Type> ptr(object);
DoStuff(ptr);
}
答案 3 :(得分:1)
这取决于SmartPointer在销毁时的作用。如果您可以将free
指定为解除分配器,则可以使用。例如,boost :: shared_ptr允许您指定删除器。
我没有足够重视你想要这个的原因。我同意其他答案,使用nothrow new
是一个更好的主意。
答案 4 :(得分:1)
可以将malloc与智能指针一起使用(您必须将返回值强制转换为目标指针类型,并提供自定义解除分配器)。但更好的选择是使用nothrow
运算符的new
版本。
答案 5 :(得分:1)
/* handle error */
中的代码是什么?对于内存不足错误,您有什么可以实际做的吗?我只是让应用程序以一个调用堆栈(核心转储)终止,所以我知道至少有一个可能导致问题的地方。
使用malloc
为C ++类和对象分配内存不是一个好主意,因为它不会确保调用构造函数,可能会留下未初始化的类,如果它们有虚拟方法,甚至可能会崩溃
只需使用new
和delete
并且不用担心捕获异常,在所有内存耗尽之后这是一个例外情况,并且不应该在应用程序的正常运行中发生。
答案 6 :(得分:1)
您可能想尝试“放置新”。见What uses are there for "placement new"?
答案 7 :(得分:1)
使用nothrow。
Nothrow常数
此常量值用作 运算符new和运算符的参数 new []表示这些功能 不得抛出异常 失败,但返回一个空指针 代替。
char* p = new (nothrow) char [1048576];
if (p==NULL) cout << "Failed!\n";
else {
cout << "Success!\n";
delete[] p;
}
答案 8 :(得分:1)
我有一个问题。
如果“Type”是一个构造函数可以抛出的类型,会发生什么?在这种情况下,仍然需要处理try / catch块中的异常。
那么放弃基于异常的方法是个好主意吗?
我想说的是,人们可以使用抽象工厂/工厂方法设计模式,并且在相对较少的文件/命名空间/类集中拥有所有“新”,而不是将它们分散在各处。这也可能有助于将try / catch块的使用限制为相对较小的代码。
答案 9 :(得分:0)
对于一个班轮:
unique_ptr<char, void (*)(void*)> buffer( (char*)malloc(size), free );