如何在C++中将 2d 矢量转换为 1d 数组?

How convert 2d vector to 1d array in C++?

本文关键字:转换 1d 数组 C++ 中将 2d      更新时间:2023-10-16

我需要能够在不使用C++智能指针的情况下做到这一点。我尝试了以下方法

double* VecToArr(std::vector<std::vector<double>> vec) {
double* newarr=new double(vec.size());
for (int i=0; i<vec.size(); i++) {
std::copy(vec[i].begin(), vec[i].end(), newarr);
newarr += vec[i].size();
}
std::cout<<"inside n";
for (int i=0; i<vec.size(); i++) {
std::cout<<newarr[i]<<"n";
}
return newarr;
}
int main(){
std::vector<double> x{1,2};
std::vector<double> y{3,4};
std::vector<std::vector<double>>vec;
vec.push_back(x);
vec.push_back(y);
double *arr=VecToArr(vec);
std::cout<<"outside n";
for (int i=0; i<4; i++) {
std::cout<<arr[i]<<"n";
}
}

但在VecToArr内部,输出为:

inside
4.54e-322 2.18e-317 4.34e-311 4.24e-314

不像我预期的那样1 2 3 4

在它之外,我得到相同的垃圾值。这是为什么呢?

另外,由于我使用newVecToArr中创建newarr,我在哪里delete它?在main.cpp,在我打印出值后,我只是做delete arr[]吗?

编辑

当我将函数更改为:

double* VecToArr(std::vector<std::vector<double>> vec) {
double* newarr=new double[vec.size()*vec[0].size()];
for (int i=0; i<vec.size(); i++) {
std::copy(vec[i].begin(), vec[i].end(), newarr);
newarr += vec[i].size();
}
std::cout<<"inside n";
for (int i=0; i<vec.size(); i++) {
std::cout<<newarr[i]<<"n";
}
return newarr;
}

输出现在3 4 (garbage) (garbage)而不是1 2 3 4

三个主要问题正如其他人在评论中提到的那样,还有更多。首先,您使用了错误类型的新表达式,new double(...)简单地为单个双精度分配内存,并使用提供的值对其进行初始化。您可能希望new double[...]分配一个双精度数组。

其次,提供给这个 new 的大小是不正确的,只表示向量的第一维(当它需要是所有嵌套向量大小的总和时)。

最后,您返回newarr,它已被函数内部的 for 循环修改,并最终指向分配发生位置的内存,您可能希望在开始时创建它的临时副本并返回它。

通过所有更改,最终的正确函数可能如下所示:

double* VecToArr(std::vector<std::vector<double>> vec) {
std::size_t totalsize = 0;
for (int i=0; i<vec.size(); i++) {
totalsize += vec[i].size();
}
double* newarr=new double[totalsize];
double* walkarr=newarr;
for (int i=0; i<vec.size(); i++) {
std::copy(vec[i].begin(), vec[i].end(), walkarr);
walkarr += vec[i].size();
}
return newarr;
}

我还建议通过常量引用传递向量,因为目前它是按值传递的,(目前)没有可能导致不必要的开销的原因。此外,您应该尝试始终使用类似std::vector(或至少智能指针)之类的东西来分配内存,而不是直接使用new/delete(除非处理低级容器实现),因为通常没有太多理由以打开程序为代价内存泄漏。

内存分配、索引和指针算术存在问题。我已经在您的代码中指出了这些。

#include <iostream>
#include <vector>
double* VecToArr(const std::vector<std::vector<double>>& vec) {
double* newarr=new double[vec.size() * vec[0].size()]; // <-- you have 4 elements (also notice square brackets)
double* newarr_ptr_copy = newarr;
for (int i=0; i<vec.size(); i++) {
std::copy(vec[i].begin(), vec[i].end(), newarr_ptr_copy);
newarr_ptr_copy += vec[i].size(); // don't lose track of newarr
}
std::cout<<"inside n";
for (int i=0; i<vec.size(); i++) {
std::cout<<newarr[i]<<"n";
}
return newarr;
}
int main(){
std::vector<double> x{1,2};
std::vector<double> y{3,4};
std::vector<std::vector<double>>vec;
vec.push_back(x);
vec.push_back(y);
double *arr=VecToArr(vec);
std::cout<<"outside n";
for (int i=0; i<4; i++) {
std::cout<<arr[i]<<"n";
}
delete [] arr; // make sure that you release the memory that you allocated
}

看看这段代码:

double* newarr=new double[vec.size()];
for (int i=0; i<vec.size(); i++) {
std::copy(vec[i].begin(), vec[i].end(), newarr);
newarr += vec[i].size();
}

一个简单的数学在这里被违反。您将newarr分配为vec的大小。目前为止,一切都好。现在,对于vec中的每个元素,您将指针递增vec[i].size- 有效地导致使用的SUM(vec[i].size())大小。这是不对的,通过访问分配边界之外的数组,程序中有未定义的行为。

请注意,我还修复了您的代码中的一个拼写错误 - 您的原始版本new double(vec.size())分配了一个双精度,而不是它们的数组。