如何在 Visual Studio C++ 11 中运行时定义二维数组?
How to define a two dimensional array during run time in Visual Studio C++ 11?
我正在尝试使用Visual Studio 2015 vc14 x64编译器在Windows上编译ORBSLAM2。该项目最初是为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 表达式的计算结果未达到常数
。在以下代码行上:
const size_t N = vDescriptors.size();
随后,二维数组定义也失败了(float Distances[N][N];
(。
在视觉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();
}
}
你的问题
您尝试在堆栈上创建一个 2D 数组(这不是标准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 矢量中以不同的方式对元素进行排序。
相关文章:
- 我可以在运行时重新定义在 OpenCascade/OCCT 标头中定义的 c++ 静态常量吗?
- 如何在 Visual Studio C++ 11 中运行时定义二维数组?
- 是否可以在运行时调用用于选择要调用的用户定义文本的逻辑?
- 在运行时使用用户定义的文本
- C++如何在运行时定义类?
- 是否有任何可能的方法将事件(自定义)附加到在运行时创建的对象?[C 构建器]
- 自定义char*插入功能多次运行时会产生运行时错误
- 上限time_point到运行时定义的持续时间
- 使用未定义符号的运行时错误:_ZN5boost6system15system_categoryEv
- 在运行时重新定义 c++ 中的 #define
- 如何使用在运行时定义的数学函数创建类
- 是否可以在运行时定义要在STXXL中排序的类型的长度
- 在运行时定义循环
- 如何制作一个在运行时定义大小的数组
- 如何在运行时定义成员数组大小
- 使用运行时定义的字符串和列表的 Sprintf
- 在运行时定义的C++全局外部常量可用于多个源文件
- 在运行时定义双精度或浮点数的精度/大小
- 在运行时定义非作用域文本
- 在运行时定义的c++纯虚方法