数组和隐式生命周期对象创建 [英] Arrays and implicit-lifetime object creation

查看:85
本文介绍了数组和隐式生命周期对象创建的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

标准将某些类型定义为隐式生命周期类型,并且其中包括数组.一些函数隐式地创建具有隐式生存期的对象(其中包括malloc等),在此处可以找到带有隐式创建具有隐式生存期的对象的操作的列表. https://en.cppreference.com/w/cpp/language/object(我希望它是正确的,但是对于其余的问题,我们假设在这种情况下, new 作为 malloc 可以用于隐式对象创建).

Some types are defined by standard as implicit-lifetime types, and arrays are among them. Some functions implicitly create objects with implicit-lifetime (malloc etc are among them), with a list of operations that implicitly create objects with implicit lifetime, found here. https://en.cppreference.com/w/cpp/language/object (I hope it is correct, but for the rest of the question let's assume that new works as malloc in this case for implicit object creation purposes).

如果没有创建其元素,隐式创建一个数组是什么意思?这是否意味着

What does it mean to implicitly create an array if it doesn't create its elements? Does it mean that

T* implicit_array = reinterpret_cast<T*>(::operator new(sizeof(T) * count, std::align_val_t{alignof(T)}) );

产生适用于指针算术的implicit_array对象,即为类型T的元素提供有效的存储,以便稍后使用放置新的位置来构造它吗?
这是否意味着 new(implicit_array + i)T {...} 是定义良好的操作,即使按照标准,不一定必须定义 implicit_array + i ? https://eel.is/c++draft/expr.unary#op-3.2 .

produces implicit_array object that is suitable for pointer arithmetic in, namely provides valid storage for elements of type T to be constructed using placement new later?
Does it mean that new (implicit_array + i) T{...} is a well defined operation, even though, by the standard, implicit_array + i is not necessarily defined? 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?

implicit_array 处理为具有k个元素的数组?

treats implicit_array as an array with k elements?

谢谢.

推荐答案

可以先为数组分配存储空间,然后再构造元素. expr.new/15 中密切相关的注释专门提到了"分配字符数组的通用习惯,以后将其他类型的对象放置到该字符数组中.".

It is possible to allocate the storage for the array, first, then construct the elements later. A closely related note in expr.new/15 specifically mentions "the common idiom of allocating character arrays into which objects of other types will later be placed".

除了 reinterpret_cast 是不安全的,而且实际上不是必需的之外,发布的代码大多遵循正确的分配-然后-构造"顺序.从分配步骤中返回的 void * 到类型化的 T * 的转换,是在构造时由放置 new 的运算符完成的.

The posted code mostly follows the proper allocate-then-construct sequence, except the reinterpret_cast is not safe and is, in fact, not necessary. The conversion from the void * returned in the allocation step to the typed T * is done by the placement new operator at construction time, instead.

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

这篇关于数组和隐式生命周期对象创建的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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