【发布时间】:2023-03-25 07:55:01
【问题描述】:
在 C 语言中,可以使用malloc(sizeof(T) * N) 分配动态数组,然后使用指针算法获取此动态数组中 i 偏移处的元素。
在 C++ 中,可以使用 operator new() 以与 malloc() 相同的方式执行类似操作,然后放置新的(例如,可以在“异常 C++:47 个工程难题、编程问题、和解决方案”由 Herb Sutter 撰写)。如果您没有,则此问题的解决方案摘要为:
T* storage = operator new(sizeof(T)*size);
// insert element
T* p = storage + i;
new (p) T(element);
// get element
T* element = storage[i];
对我来说,这看起来是合法的,因为我要求一块具有足够内存的内存来容纳大小 = sizeof(T) 的 N 个对齐元素。由于sizeof(T) 应该返回一个对齐的元素的大小,并且它们一个接一个地放置在一块内存中,所以在这里使用指针算法是可以的。
然后我被指向如下链接:http://eel.is/c++draft/expr.add#4 或 http://eel.is/c++draft/intro.object#def:object 并声称在 C++ 中 operator new() 不返回数组对象,因此指针算术返回的内容并将其用作数组是未定义的与 ANSI C 不同的行为。
我不擅长这么低级的东西,我真的很想通过阅读以下内容来理解:https://www.ibm.com/developerworks/library/pa-dalign/ 或以下内容:http://jrruethe.github.io/blog/2015/08/23/placement-new/ 但我仍然无法理解 Sutter 是否完全错了?
我明白alignas 在以下结构中是有意义的:
alignas(double) char array[sizeof(double)];
(c)http://georgeflanagin.com/alignas.php
如果数组似乎不在double 的边界内(可能在char 之后的结构中运行在2 字节读取处理器上)。
但这是不同的——我已经从堆/空闲存储中请求了内存,特别是请求 operator new 返回内存,该内存将保持与sizeof(T)对齐的元素。
总结一下,如果这是 TL;DR:
- 是否可以将
malloc()用于 C++ 中的动态数组? - 是否可以在没有
alignas关键字的旧 C++ 中对动态数组使用operator new()和放置 new? - 在
operator new()返回的内存上使用指针算术是否未定义行为? - Sutter 是否建议在某些古董机器上可能会破坏的代码?
对不起,如果这是愚蠢的。
【问题讨论】:
-
是否可以在 C 中将 malloc() 用于动态数组? - 你想写 C++?
-
你能把整个代码放在这里吗?因为您提供的代码甚至无法编译(在第一行,至少有一个丢失的演员表)。
-
@Galik 它在eel.is/c++draft/expr.add#footnote-85 中说。我不认为指针被认为指向单个对象。在分配的内存中没有构造对象。
-
是的,如我所见,该代码确实有 UB。但是,在我看来,需要修复的是标准,而不是 Herb 的代码。有趣的是,为什么我们对指针算法有这样一个限制规则。
-
@Galik 我不太清楚,但在我的业余阅读中,
possibly-hypothetical指的是实际数组之后的hypothetical x[n],而 4.2 的排位赛if也没有使用它。
标签: c++ arrays language-lawyer placement-new alignas