转换.c ++后,在char类型的原始缓冲区上调用delete [英] Calling delete on original buffer of char type after casting .c++

查看:106
本文介绍了转换.c ++后,在char类型的原始缓冲区上调用delete的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在此答案中:
https://stackoverflow.com/a/222578/4416169

in this answer: https://stackoverflow.com/a/222578/4416169

使用以下代码:

char *buf  = new char[sizeof(string)]; // pre-allocated buffer
string *p = new (buf) string("hi");    // placement new
string *q = new string("hi");          // ordinary heap allocation

有一条评论说:

请记住,在删除缓冲区之前手动将字符串解构,这就是下面的注释所假定的。


严格来说,这是未定义的行为在原始
char缓冲区上调用delete []。通过使用new放置,通过重新使用
个原始char对象的存储,它们的生命期结束了。如果现在调用
delete [] buf,则指向的对象的动态类型不再与
匹配其静态类型,因此您具有不确定的行为。使用操作符new / operator delete分配原始内存
以供放置new使用是更一致的。

Strictly, it's undefined behaviour to call delete[] on the original char buffer. Using placement new has ended the lifetime of the original char objects by re-using their storage. If you now call delete[] buf the dynamic type of the object(s) pointed to no longer matches their static type so you have undefined behaviour. It is more consistent to use operator new/operator delete to allocate raw memory inteded for use by placement new.

是这个评论对它的主张是正确的吗?我们是否应该像下面的代码那样使用new运算符创建一个void *指针的缓冲区,并使用下面的代码删除该运算符,以删除它?:

Is this comment correct on what it claims? Should we instead create a buffer of void* pointers with operator new to create it and operator delete to delete it as in the following code?:

void *raw_memory = operator new(sizeof(int));
int *dynamicInt = new(raw_memory) int;
operator delete(raw_memory);

此代码^^严格等于以下代码吗?:

is this code^^ strictly equivalent to the following code?:

void *raw_memory = operator new[](sizeof(int));//notice the [] after new
int *dynamicInt = new(raw_memory) int;
operator delete[](raw_memory);//notice the [] after delete

之后的[]只需使用char *缓冲区并执行通常的数组删除和新建操作即可?

or is it ok to simply use a char* buffer and do the usual array delete and new?

推荐答案


转换后的char类型的原始缓冲区。c ++

Calling delete on original buffer of char type after casting .c++

请注意,示例中没有转换。

Note that there is no casting involved in the examples.



使用placement new通过重新使用原始存储对象的存储来结束其原始生存期。

Using placement new has ended the lifetime of the original char objects by re-using their storage.


这当然是正确的。标准报价:

This is certainly correct. Standard quote:


[basic.life] ...对象的生存期o ...在以下情况下结束:...该对象占用的存储空间... ...被未嵌套在o中的对象重用。

[basic.life] ... The lifetime of an object o ... ends when: ... the storage which the object occupies is ... reused by an object that is not nested within o







如果您现在调用delete [] buf,则指向的对象的动态类型不再与它们的静态类型匹配,因此您的行为不确定。

If you now call delete[] buf the dynamic type of the object(s) pointed to no longer matches their static type so you have undefined behaviour.


可能的违反规则是:


[expr.delete]在单对象删除表达式中,如果要删除的对象的静态类型与它的动态类型不同,并且所选的释放函数(参见下文)不是销毁操作符删除,则静态类型应为要删除的对象的动态类型的基类。删除,并且静态类型应具有虚拟析构函数或行为未定义。 在数组删除表达式中,如果要删除的对象的动态类型与其静态类型不同,则行为是不确定的。

让我们看看什么是动态类型。意思是:

Let us take a look at what "dynamic type" means:


glvalue所引用的最派生对象([intro.object])的类型

[defns.dynamic.type] type of the most derived object ([intro.object]) to which the glvalue refers



[intro.object]如果完整的对象,数据成员或数组元素属于类类型,则认为其类型是最派生类,以区别于任何基类子对象的类类型;具有最大派生类类型或非类类型的对象称为最大派生对象。

[intro.object] If a complete object, a data member, or an array element is of class type, its type is considered the most derived class, to distinguish it from the class type of any base class subobject; an object of a most derived class type or of a non-class type is called a most derived object.

因此,这里的问题是没有对象,因此没有大多数派生对象的类型可以与静态类型匹配。

So, the issue here is that there is no object, and therefore there is no most derived object whose type could match with the static type.

对我来说,这似乎有点技术性,因为我们正在考虑一个琐碎的非类类型。

To me, this seems like bit of a technicality because we are considering a trivial non-class type. This technicality is not a problem with a bare operator new.


我们应该创建一个 void * 具有运算符new的指针

Should we instead create a buffer of void* pointers with operator new

更好的是,我们可能应该使用 std :: allocator< std :: string> ::分配,内部调用 :: operator new 。这样一来,我们的程序就可以更轻松地容纳自定义分配器,并且无需根据元素的大小来计算数组的大小。

Even better, we probably should use std::allocator<std::string>::allocate which internally calls ::operator new. This makes our program easier to accommodate custom allocators and obviates the need to calculate the sizes of arrays based on the size of the element.

这篇关于转换.c ++后,在char类型的原始缓冲区上调用delete的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆