c++ - 从新分配的内存分配给对象

标签 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] = T(1, 2); //is this legal? thechnically object at data[pos] is in some undetermenistic state.
}

最佳答案

这仅对标量类型(如数字类型或任何指针类型)或具有 "trivial" default constructor 的类类型(包括 union )有效,或此类类型的数组。如果 T 是具有非平凡默认构造函数或没有默认构造函数的类类型,或者此类类型的数组,则在未创建对象的内存上调用任何成员函数是未定义的行为,即使如果该成员是复制赋值运算符。

(当前的 C++20 草案在 [basic.life] 中有一些变化,似乎也排除了普通默认构造函数的情况,但我不完全确定其含义。)

执行此操作的正确且安全的方法是使用“placement new”:

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

上面将参数 1, 2 直接传递给由 new 表达式调用的 T 的构造函数。如果该示例过于简单化并且您确实有一些其他原因来默认初始化对象(假设默认初始化是可能的)然后重新分配它,那也很简单:

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

关于c++ - 从新分配的内存分配给对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57103342/

相关文章:

c++ - 从 matroska(mkv、webm)到音频(C++ 通过 libvorbis)的解码循环逻辑

java - 类转换异常 : java. lang.String 与 [Ljava.lang.Object; 不兼容;

java - 从父类访问

javascript - 赋值返回的值

java - Java 中方法调用和参数之间的求值顺序

C++ 错误 C2040 : 'e' : 'Logger' differs in levels of indirection from 'const std::exception &'

C++ 编译错误包括 X11/X.h X11/Xlib.h

c++ - 为什么我们需要删除复制赋值运算符中的指针

c++ - 静态方法中的对象创建正在更改其他静态对象的私有(private)成员变量

object - 在SSIS中插入两个变量到对象