有些类型被标准定义为隐式生命周期类型,数组就是其中之一。
一些函数隐式创建具有隐式生命周期的对象(malloc 等就是其中之一),
包含隐式创建具有隐式生存期的对象的操作列表,可在此处找到。https://en.cppreference.com/w/cpp/language/object https://en.cppreference.com/w/cpp/language/object(我希望这是正确的,但对于问题的其余部分,我们假设new
作为malloc
在本例中用于隐式对象创建目的)。
这意味着什么隐式创建一个数组如果它不创建它的元素?是不是意味着
T* implicit_array = reinterpret_cast<T*>(::operator new(sizeof(T) * count, std::align_val_t{alignof(T)}) );
生成适合指针算术的implicit_array对象,即为稍后使用placement new构造的类型T的元素提供有效的存储?
是不是意味着new (implicit_array + i) T{...}
是一个定义明确的操作,尽管按照标准,implicit_array + i
是不是一定要定义?https://eel.is/c++draft/expr.unary#op-3.2 https://eel.is/c++draft/expr.unary#op-3.2.
或者这意味着
std::byte* memory =
reinterpret_cast<std::byte*>(::operator new(sizeof(T) * capacity, std::align_val_t{alignof(T)}));
new (memory) T{args1 ...}
// build more objects
new (memory + (k-1)*sizeof(T) ) T{args_k ...}
T* implicit_array = std::launder(reinterpret_cast<T*>(memory) ); // does it produce array of k elements?
treats implicit_array
作为一个有 k 个元素的数组?
Thanks.
可以先为数组分配存储空间,然后再构造元素。密切相关的注释表达式.new/15 https://eel.is/c++draft/expr.new#15特别提到“分配字符数组的常见习惯用法,稍后将在其中放置其他类型的对象".
发布的代码大多遵循正确的分配然后构造顺序,除了reinterpret_cast
不安全,事实上也没有必要。转换自void *
在分配步骤中返回给类型化的T *
是通过放置完成的new
相反,在施工时操作员。
void *alloc_array(size_t cnt)
{
return ::operator new(sizeof(T) * cnt, std::align_val_t{alignof(T)});
}
T *construct_array(void *buf, size_t cnt)
{
T *arr = new(buf) T {...}, *p = arr;
for(int i = 1; i < cnt; i++)
p = new(p + 1) T {...};
return arr;
}
void destruct_array(T *arr, size_t cnt)
{
for(int i = cnt; i--; )
arr[i].~T();
}
void free_array(void *buf, size_t cnt)
{
::operator delete(buf, sizeof(T) * cnt, std::align_val_t{alignof(T)});
}
使用示例:
void *buf = alloc_array(cnt);
T *arr = construct_array(buf, cnt);
for(int i = 0; i < cnt; i++)
T &ob = arr[i]; /* ... */
destruct_array(arr, cnt);
free_array(buf, cnt);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)