是否可以使用 C++智能指针与C的malloc一起使用?

发布于 2024-09-13 21:17:53 字数 448 浏览 4 评论 0原文

我的一些代码仍然使用 malloc 而不是 new。原因是因为我害怕使用 new 因为它会抛出异常,而不是返回 NULL,我可以轻松检查。将每次调用 new 包装在 try{}catch(){} 中看起来也不太好。而使用 malloc 时,我只需执行 if (!new_mem) { /* 处理错误 */ } 即可。

因此我有一个问题。我可以将智能指针与 malloc 一起使用吗?

类似这样的东西:

SmartPointer<Type> smarty = malloc(sizeof(Type));

类似这样的东西。

这可能吗?

Some of my code still uses malloc instead of new. The reason is because I am afraid to use new because it throws exception, rather than returning NULL, which I can easily check for. Wrapping every call to new in a try{}catch(){} also doesn't look that good. Whereas when using malloc I can just do if (!new_mem) { /* handle error */ }.

Therefore I have a question. Can I use smart pointers together with malloc?

Something like:

SmartPointer<Type> smarty = malloc(sizeof(Type));

Something like this.

Is this possible?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

等数载,海棠开 2024-09-20 21:17:53

如果您使用 shared_ptrunique_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++ 时,最好正确使用异常,而不是避免异常,特别是在分配失败方面。在大多数情况下,您无法成功地从尝试进行分配的函数中的分配失败中恢复,因此异常可以帮助您在实际能够处理错误的情况下处理错误。

If you are using shared_ptr or unique_ptr, you can specify a custom deleter. For example,

struct free_delete
{
    void operator()(void* x) { free(x); }
};

This can be used with shared_ptr like so:

std::shared_ptr<int> sp((int*)malloc(sizeof(int)), free_delete());

If you are using unique_ptr, the deleter is a part of the unique_ptr's type, so the deleter needs to be specified as a template argument:

std::unique_ptr<int, free_delete> up((int*)malloc(sizeof(int)));

However, it is better to use exceptions correctly, rather than avoiding them, when writing C++, especially with respect to allocation failures. In most cases, you cannot successfully recover from an allocation failure in the function trying to do the allocation, so exceptions can help you to handle the error where you are actually capable of handling it.

ぺ禁宫浮华殁 2024-09-20 21:17:53

您可以将 nothrow 关键字与 new 运算符一起使用,这将返回 NULL 而不是抛出异常。详细信息请参见下面的链接:
http://www.cplusplus.com/reference/std/new/nothro/

You can use nothrow keyword with the new operator, which will return NULL rather that throw an exception. For details see link below:
http://www.cplusplus.com/reference/std/new/nothrow/

你另情深 2024-09-20 21:17:53

最好的解决方案是使用new (std::nothrot) 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);
}

The best solution is to use new (std::nothrow) Type. This will act just like new Type, but will give null rather than throwing if it fails. This will be much easier than trying to make malloc behave like new.

If you really must use malloc, then remember to construct and destruct the object correctly:

void* memory = malloc(sizeof(Type));
Type* object = new (memory) Type;
object->~Type();
free(object); // or free(memory)

You can use this with a some smart pointers by giving it a custom deleter:

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);
}

But this would be much simpler using non-throwing new:

if (Type* object = new (std::nothrow) Type)
{        
    std::shared_ptr<Type> ptr(object);
    DoStuff(ptr);
}
泼猴你往哪里跑 2024-09-20 21:17:53

/*处理错误*/中包含什么代码?对于内存不足错误,您实际上可以做些什么吗?我只是让应用程序通过调用堆栈(核心转储)终止,因此我至少知道一个可能导致问题的地方。

使用 malloc 为 C++ 类和对象分配内存不是一个好主意,因为它无法确保调用构造函数,可能会留下未初始化的类,如果它们具有虚拟方法,这些类甚至可能会崩溃。

只需使用 newdelete 即可,不用担心捕获异常,毕竟内存不足是一种异常情况,在应用程序的正常运行中不应发生。

What code goes in /* handle error */? Is there anything you can actually DO with an out-of-memory error? I just let the application terminate with a call stack (core dump) so I have an idea at least one possible place that might be causing problems.

Using malloc to allocate memory for C++ classes and objects is not a good idea because it won't make sure that the constructors are called, possibly leaving you with uninitialized classes that may even crash if they have virtual methods.

Just use new and delete and don't worry about catching the exception, after all running out of memory IS an exceptional case and should not happen in normal runs of the application.

江南月 2024-09-20 21:17:53

这取决于智能指针在销毁时所做的事情。如果您可以指定 free 作为释放器,那么就可以工作。例如,boost::shared_ptr 允许您指定删除器。

我没有足够重视你想要这个的原因。我同意其他答案,即使用 nothrow new 是一个更好的主意。

It depends on what the SmartPointer does on destruction. If you can specify free as a deallocator, that could work. For example, boost::shared_ptr allows you to specify a deleter.

I didn't pay enough attention to your reason for wanting this. I agree with the other answers that using the nothrow new is a much better idea.

心是晴朗的。 2024-09-20 21:17:53

您可能想尝试“新展示位置”。请参阅“展示位置新”有什么用途?

You might want to try "placement new". See What uses are there for "placement new"?

雪花飘飘的天空 2024-09-20 21:17:53

使用nothrow

无投掷常数

该常量值用作
运算符 new 和运算符的参数
new[] 来表明这些函数
不得抛出异常
失败,但返回空指针
相反。

char* p = new (nothrow) char [1048576];
if (p==NULL) cout << "Failed!\n";
else {
    cout << "Success!\n";
    delete[] p;
}

Use nothrow.

Nothrow constant

This constant value is used as an
argument for operator new and operator
new[] to indicate that these functions
shall not throw an exception on
failure, but return a null pointer
instead.

char* p = new (nothrow) char [1048576];
if (p==NULL) cout << "Failed!\n";
else {
    cout << "Success!\n";
    delete[] p;
}
流心雨 2024-09-20 21:17:53

我有一个问题。

如果“Type”是构造函数可以抛出异常的类型,会发生什么情况?在这种情况下,仍然需要在 try/catch 块中处理异常。

那么放弃基于异常的方法是个好主意吗?

我想说的是,人们可以使用抽象工厂/工厂方法设计模式,并将所有“新内容”放在相对较少的一组文件/命名空间/类中,而不是将它们分散在各处。这也可能有助于将 try/catch 块的使用限制在相对较少的代码中。

I have a question.

What happens if "Type" is a type whose constructor can throw? In that case, one still needs to handle exceptions in a try/catch block.

So is it a good idea to abandon exception based approach?

I would say that one can use the Abstract Factory/Factory Method design pattern and have all the 'new's in relatively lesser set of files/namespaces/classes, rather than these being scattered all around the place. That may also help in restricting the use of try/catch block to a relatively lesser code.

她比我温柔 2024-09-20 21:17:53

对于单行:
unique_ptr;缓冲区((char*)malloc(大小),空闲);

for oneliner:
unique_ptr<char, void (*)(void*)> buffer( (char*)malloc(size), free );

謸气贵蔟 2024-09-20 21:17:53

可以将 malloc 与智能指针一起使用(不过,您必须将返回值转换为目标指针类型,并提供自定义释放器)。但更好的选择是使用 nothrow 版本的 new 运算符。

http://www.cplusplus.com/reference/std/new/nothro/< /a>

It is possible to use malloc with smart pointers (you have to cast return value to target pointer type, though and provide custom deallocator). But better option is to use nothrow version of new operator.

http://www.cplusplus.com/reference/std/new/nothrow/

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文