c ++使用数组而不调用构造函数

c++ using an array without calling constructor

我的任务是在不调用 T(模板)构造函数的情况下创建模板类型数组。之后我想用 std::move 将一些值从另一个数组移动到这个数组。我怎么能在 C++ 中做到这一点?这是我的代码:

void *temp = malloc((end-begin) * sizeof(T));
for (unsigned int i = begin; i < end; ++i){
    temp[i] = std::move(array[i]);
}

但这行不通。编译器表示如下:指向不完整类型的指针的下标 'void'。

void 数组没有意义。 void 是一个不完整的类型(并且没有大小),因此 temp[i] 会生成您所看到的错误。

要实现您想做的事情,为什么不使用 std::vector,并在项目可用时将其推送到其中?

std::vector<T> temp;
for (unsigned int i = begin; i < end; ++i){
    temp.push_back(std::move(array[i]));
}

尝试

T *temp = (T*) malloc((end-begin) * sizeof(T));

如果您真的想手工完成,您正在寻找新的安置。首先你分配一个 "raw buffer" of unsigned chars:

unsigned char* buf = new unsigned char(end-begin);

或:

auto buf = std::make_unique<unsigned char[]>(end-begin);

然后你将 new (buf) Tnew (buf+sizeof(T)) Tnew (buf+2*sizeof(T)) T 到 "emplace" 之类的东西写入内存 space。

问题是,在上面的例子中我完全忽略了对齐要求,这很危险。

因此,与其复制内存池和 std::vector 所做的事情,不如使用 std::vector!

std::vector<T> vec;
vec.reserve(end-begin);
for (unsigned int i = begin; i < end; ++i){
   vec.push_back(std::move(array[i]);
}

大功告成。

正如其他人指出的那样,void 没有定义大小,因此 void* 不能作为数组进行索引。

temp[1]从哪里开始?

一个简单的修复:

T *temp = std::malloc((end-begin) * sizeof(T));

与以下项一起使用时同样糟糕:

temp[i] = std::move(array[i]);

该代码将调用赋值运算符,如果在对 temp[i] 中的垃圾进行操作时会失败。例如,如果分配显式或隐式取消分配分配目标中的资源,它将对未初始化的 temp[i] 进行操作并失败。

如果(如果!)您这样做了,正确的代码将是:

std::memcpy(temp+i*sizeof(i),array[I],sizeof(T));

这行代码本质上是假设 T 是一个平凡可复制的类型。

第一行假设 T 的对象有一个简单的默认构造函数。 如果 T 有一个简单的默认构造函数,大多数编译器将优化元素初始化(这是我假设提问者试图避免的)。

所以推荐的代码(使用for循环)是:

T* temp= new T[end-being];
for(unsigned int i=begin;i<end;++i){
    temp[i-begin]=array[i];
}

注意:此代码还修复了原始代码中的一个错误,该错误会在 begin!=0 时中断。 该代码似乎正在从 array 的中间复制一个子部分到 temp 的开头,但忘记从 temp 的索引 0 开始。

但推荐的 C++ 复制方法是:

T* temp= new T[end-being];
std::copy(array+begin,array+end,temp);

良好的实施将尽可能确定并利用任何大容量内存操作。 所以隐含地这应该导致 std::memmove(temp,array,(end-begin)*sizeof(T)); 如果有效。

编译器可能无法识别的唯一最后一个转折点是可能稍微更高效

std::memcpy(temp,array,(end-begin)*sizeof(T));

在这种情况下实际上是有效的,因为我们知道 temp 不能与 array 重叠(更不用说被复制的范围了)。

脚注:正如评论中所指出的,最传统的 C++ 方法是使用 std::vector,通常可以假定它在幕后使用这些优化。但是,如果由于某种原因无法或不需要重新构建应用程序,则此答案提供了重写所提供代码的有效有效方法。