gpt4 book ai didi

c++ - 如何在 Visual Studio C++ 11 运行时定义二维数组?

转载 作者:行者123 更新时间:2023-11-27 23:44:03 25 4
gpt4 key购买 nike

我正在尝试编译 ORBSLAM2在 Windows 上使用 Visual Studio 2015 vc14 x64 编译器。该项目最初是为 GNU GCC 开发的。我现在遇到以下问题:

// Compute distances between them
const size_t N = vDescriptors.size();

float aDistances[N][N];
for(size_t i=0;i<N;i++) {
aDistances[i][i]=0;
for(size_t j=i+1;j<N;j++) {
int distij = ORBmatcher::DescriptorDistance(vDescriptors[i],vDescriptors[j]);
aDistances[i][j]=distij;
aDistances[j][i]=distij;
}
}

编译时出现这个错误:

C2131 expression did not evaluate to a constant

...在这行代码中:

const size_t N = vDescriptors.size();

随后二维数组定义也失败了(float Distances[N][N];)。

在 Visual-C++ 中解决这个问题的最佳方法是什么?

更新:这是完整的函数代码:

void MapPoint::ComputeDistinctiveDescriptors() {

// Retrieve all observed descriptors
vector<cv::Mat> vDescriptors;
map<KeyFrame*,size_t> observations;

{
unique_lock<mutex> lock1(mMutexFeatures);
if(mbBad)
return;
observations=mObservations;
}

if(observations.empty())
return;

vDescriptors.reserve(observations.size());

for(map<KeyFrame*,size_t>::iterator mit=observations.begin(), mend=observations.end(); mit!=mend; mit++) {
KeyFrame* pKF = mit->first;
if(!pKF->isBad())
vDescriptors.push_back(pKF->mDescriptors.row(mit->second));
}

if(vDescriptors.empty())
return;

// Compute distances between them
const size_t N = vDescriptors.size();

float aDistances[N][N];
for(size_t i=0;i<N;i++) {
aDistances[i][i]=0;
for(size_t j=i+1;j<N;j++) {
int distij = ORBmatcher::DescriptorDistance(vDescriptors[i],vDescriptors[j]);
aDistances[i][j]=distij;
aDistances[j][i]=distij;
}
}

// Take the descriptor with least median distance to the rest
int BestMedian = INT_MAX;
int BestIdx = 0;
for(size_t i=0;i<N;i++) {
vector<int> vDists(aDistances[i], aDistances[i]+N);
sort(vDists.begin(),vDists.end());
int median = vDists[0.5*(N-1)];
if(median<BestMedian) {
BestMedian = median;
BestIdx = i;
}
}

{
unique_lock<mutex> lock(mMutexFeatures);
mDescriptor = vDescriptors[BestIdx].clone();
}
}

最佳答案

你的问题

您尝试在堆栈上创建一个二维数组(这不是标准的 C++,尽管它可能适用于某些编译器)。为此,需要在编译时知道大小,当您在可能不是 constexpr 的对象上调用 size() 时,情况并非如此。

快速修复

一个开箱即用的快速修复方法是在堆上分配内存(不要忘记稍后删除数组)

float** aDistances = new float[N][N];

删除可以在一个看起来像这样的函数中完成

template <typename T>
void delete2DArray(T** ptr, size_t NumRows)
{
for (size_t i = 0; i < NumRows; i++)
{
delete[] ptr[i];
}
delete[] ptr;
}

修复

您将不得不使用动态内存分配。为此,您可以通过在 std::vector 周围添加一个包装类来尝试以下方法(这应该是可能的,因为您说范围非常易于管理)

template <typename T>
class Array2D
{
public:
Array2D(size_t numrows, size_t numcols) :
rows(numrows), columns(numcols), array2d(rows * columns)
{}

T& operator()(size_t row, size_t column)
{
return array2d[row * columns + column];
}

const T& operator()(size_t row, size_t column) const
{
return array2d[row * columns + column];
}

T* getRow(size_t row)
{
return &array2d[row * columns];
}


private:
size_t rows;
size_t columns;
std::vector<T> array2d;
};

你必须像这样修改你的代码:

// Compute distances between them
const size_t N = vDescriptors.size();

Array2D<float> aDistances(N,N);
for (size_t i = 0; i < N; i++) {
aDistances(i,i) = 0;
for (size_t j = i + 1; j < N; j++) {
int distij = ORBmatcher::DescriptorDistance(vDescriptors[i], vDescriptors[j]);
aDistances(i,j) = distij ;
aDistances(j,i) = distij ;
}
}

如您所见,访问元素的语法略有变化 [x][y] -> (x,y)。

编辑

由于 OP 修改了问题,我注意到 Distances 被第二次使用,这也需要注意。为此,您必须将 getColumn 方法(见上文)添加到 Array2D 类。比你还需要修改

// Take the descriptor with least median distance to the rest
int BestMedian = INT_MAX;
int BestIdx = 0;
for(size_t i=0;i<N;i++) {
vector<int> vDists(aDistances.getRow()[i], aDistances.getRow()[i]+N);
sort(vDists.begin(),vDists.end());
int median = vDists[0.5*(N-1)];
if(median<BestMedian) {
BestMedian = median;
BestIdx = i;
}
}

注意:我不确定我是否做对了——也许你必须得到一个列而不是行(为时已晚,无法直接思考)。如果是这种情况,您还应该更改 Array2D 类的内存布局,即在底层 1D-Vector 中对元素进行不同的排序。

关于c++ - 如何在 Visual Studio C++ 11 运行时定义二维数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52175168/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com