C++ 从新分配的内存中分配到对象
为数组分配行内存,然后对该数组中的对象调用赋值运算符,这符合标准吗 例如:C++ 从新分配的内存中分配到对象,c++,object,assignment-operator,C++,Object,Assignment Operator,为数组分配行内存,然后对该数组中的对象调用赋值运算符,这符合标准吗 例如: template <typename T> void func(size_t sz, size_t pos) { static constexpr std::align_val_t __al = std::align_val_t(alignof(T)); T* data= static_cast<T*>(::operator new(sz * sizeof(T), __al)); data[pos
template <typename T>
void func(size_t sz, size_t pos)
{
static constexpr std::align_val_t __al = std::align_val_t(alignof(T));
T* data= static_cast<T*>(::operator new(sz * sizeof(T), __al));
data[pos] = T(1, 2); //is this legal? thechnically object at data[pos] is in some undetermenistic state.
}
模板
无效函数(大小和位置)
{
静态constexpr std::align_val_t_ual=std::align_val_t(alignof(t));
T*data=static_cast(::运算符new(sz*sizeof(T),u al));
data[pos]=T(1,2);//这合法吗?data[pos]处的技术对象处于某种未检测状态。
}
不,它无效<代码>数据[pos]不仅仅处于某种不确定状态。在数据所指向的内存中根本不存在T
对象。因此,对不存在的对象调用T::operator=
是无效的
在这种情况下,您需要使用placementnew
:
template <typename T>
void func(size_t sz, size_t pos)
{
static constexpr std::align_val_t __al = std::align_val_t(alignof(T));
T* data = static_cast<T*>(::operator new(sz * sizeof(T), __al));
T* ptr = new (data + pos) T(1, 2);
}
模板
无效函数(大小和位置)
{
静态constexpr std::align_val_t_ual=std::align_val_t(alignof(t));
T*data=static_cast(::运算符new(sz*sizeof(T),u al));
T*ptr=新(数据+位置)T(1,2);
}
这将在内存地址data+pos
处构造一个新的T
对象。在释放分配的内存之前,您需要手动调用T
的析构函数来销毁该对象。这仅对标量类型(如数值类型或任何指针类型)或具有数组的类类型(包括联合)有效。如果T
是具有非平凡默认构造函数或无默认构造函数的类类型,或此类类类型的数组,则调用内存中未创建对象的任何成员函数是未定义的行为,即使该成员是复制赋值运算符也是如此
(当前的C++20草案有一些变化,其中似乎也排除了普通默认构造函数的情况,但我不能完全确定其含义。)
正确且安全的方法是使用“placement new”:
不要使用以两个下划线开头的标识符。那些是为C++实现保留的。@ ascPoop-这只是规则中包含两个连续下划线的名字的特例。@ ReMyLeBeAube是从一个下划线开始的标识符,然后是大写字母,或者包含两个连续下划线。@ AsChisher你是对的,我误解了所说的。
template <typename T>
void func(size_t sz, size_t pos)
{
static constexpr std::align_val_t al = std::align_val_t(alignof(T));
std::byte* buffer = static_cast<std::byte*>(::operator new(sz * sizeof(T), al));
T* data = ::new(static_cast<void*>(buffer + pos*sizeof(T))) T(1, 2);
}
template <typename T>
void func(size_t sz, size_t pos)
{
static constexpr std::align_val_t __al = std::align_val_t(alignof(T));
std::byte* buffer = static_cast<std::byte*>(::operator new(sz * sizeof(T), al));
T* data = ::new(static_cast<void*>(buffer + pos*sizeof(T))) T(1, 2);
// Whatever other logic...
data[pos] = T(1, 2);
}