0

我正在使用 CLHEP 库,但遇到了一些困难。在进行这些更改之前,我一直在生成一组粒子动量作为 CLHEP 对象的向量 (std::vector),然后将它们转换为普通数组的向量 - 仍然包含相同的动量 - 以供另一个程序 (MadGraph) 使用。我想把这个转换例程放到一个新函数中,所以我做了这个:

std::vector<double*> MadGraphConvert(vector<CLHEP::HepLorentzVector> p) {

double ptemp[6][4];

for (int i = 0; i < 6; i++) {
    ptemp[i][0] = p.at(i).e();
    ptemp[i][1] = p.at(i).x();
    ptemp[i][2] = p.at(i).y();
    ptemp[i][3] = p.at(i).z();
}

// Give particles to MG in a 'vector of arrays' format
std::vector<double*> p_MG;

p_MG.push_back(ptemp[0]);
p_MG.push_back(ptemp[1]);
p_MG.push_back(ptemp[2]);
p_MG.push_back(ptemp[3]);
p_MG.push_back(ptemp[4]);
p_MG.push_back(ptemp[5]);

return p_MG;
}

现在,当我运行我的代码时,其他代码中的某些内容会引发段错误,但我认为我正在传递以前的内容?我的旧转换集如下所示:

    p[0][0] = pa.e();
    p[0][1] = pa.x();
    p[0][2] = pa.y();
    p[0][3] = pa.z();

    p[1][0] = pb.e();
    p[1][1] = pb.x();
    p[1][2] = pb.y();
    p[1][3] = pb.z();
.
'
'
    std::vector<double*> p_MG;

    p_MG.push_back(p[0]);
    p_MG.push_back(p[1]);
    p_MG.push_back(p[2]);
    p_MG.push_back(p[3]);
    p_MG.push_back(p[4]);
    p_MG.push_back(p[5]);

如果有人能发现这两种方法的区别在哪里,我将不胜感激!干杯杰克

4

1 回答 1

4

包含悬空指针,vector因为它正在填充来自局部变量数组的地址,当函数返回时,该数组ptemp超出范围。MadGraphConvert()取消引用悬空指针是未定义的行为,在这种情况下,它会导致分段错误。

使用 astd::vector<std::vector<double>>代替:

std::vector<std::vector<double>> ptemp(6, std::vector<double>(4));

for循环将按原样工作(因为此构造函数创建具有六个元素的s vector,每个元素是vector四个doubles 中的另一个)并返回ptemp(记住更改 s 的返回值MadGraphConvert())。


如果,如对此答案的评论,类型更改被禁止,则double[4]使用动态分配数组new。现在vector拥有数组,并且delete[]在不再需要时必须使用它们:

// In function.
std::vector<double*> ptemp(6); // By default, created with six null pointers.
try
{
    for (size_t i(0), count(ptemp.size()); i < count; i++)
    {
        ptemp[i] = new double[4];
        // Remainder of loop as before.
    }
}
catch (std::exception const&) // std::out_of_range, std::bad_alloc
{
    // Exception safety.
    // delete[] whatever was allocated, remember that
    // delete[] on a null pointer is a no-op so no
    // prior check required.
    for (auto i : ptemp) delete[] i;
    throw;
}

然后返回ptemp。稍后,何时vector不再需要:

// c++11
for (auto i : ptemp) delete[] i;

// c++03
for (std::vector<double*>::iterator i(ptemp.begin());
     i != ptemp.end();
     i++)
{
    delete[] (*i);
}
于 2013-03-04T12:39:43.193 回答