2

我有一个指向向量的指针向量:

main(...)
{
  //...
  std::vector< std::vector<double> * > ds = getDS(...)
  //...
}

std::vector<std::vector<double> * > getDS(int m, ...)
{
  std::vector<std::vector<double> * > wavefunctions = *(new std::vector<std::vector<double>*>(m));
  int n = int( params.rmax() / params.dr() );
  std::ifstream input_wf;
  input_wf.open(filename.c_str());
  input_wf.setf(std::ios::showpoint | std::ios::scientific);
  for(int i=0; i < nbasis; i++)
  {
    std::vector<double> *wf = new std::vector<double>(n);
    //(wavefunctions[i]) = new std::vector<double>(n);
    for (unsigned int ir=0; ir < wf->size(); ir++)
      input_wf >> ( *wf )[ir];
    wavefunctions.push_back(wf);
  }
  input_wf.close();
  return wave functions;
}

wavefunctions[0]->at(some legal value)但是,在调试期间,当我通过循环一次后尝试访问时,我不断收到 EXC_BAD_ACCESS 错误。(那里应该有一些东西,但我不确定为什么没有......有什么想法吗?

4

4 回答 4

2

下一行,

  std::vector<std::vector<double> * > wavefunctions = *(new std::vector<std::vector<double>*>(m));

在您的情况下存在问题,原因有两个 -

  1. 它会导致内存泄漏,因为创建的对象new复制wavefunctions中,然后指向它的指针丢失。这不是Java...
  2. 它在您的向量中分配m条目。Subsequentpush_back添加到该m条目中,因此当您尝试访问时,您实际上访问的是在此行中创建的条目,而不是循环wavefunctions[0]中推送的第一个条目。for

要解决此问题,请将行更改为

std::vector<std::vector<double> * > wavefunctions;
wavefunctions.reserve(m);

reserve方法确保您不会在push_back's 期间进行重新分配。

最后一点,根据具体情况,编译器可能会也可能不会优化函数返回时执行的向量的固有副本。可以肯定的是,您可能想了解更多关于 r 值引用 ( &&) 或简单地按地址返回向量(即,作为类型vector<...> *和返回类型的另一个参数void)。

于 2012-07-16T22:41:26.287 回答
1

该代码看起来应该对我有用,但是动态分配太多了。(尽管您拼写了返回值。) user1071136 发现了错误。

大多数时候,你永远不应该输入delete,而且几乎永远不要输入new。您也可以在其构造函数中打开一个流,然后流关闭自己,您不必这样做。您还忘记检查流状态,看看它是否读入了任何值。

std::vector<std::vector<double>> getDS(int m, ...)
{
  std::ifstream input_wf(filename.c_str());
  input_wf.setf(std::ios::showpoint | std::ios::scientific);

  int n = int( params.rmax() / params.dr() );
  std::vector<std::vector<double>> wavefunctions(m, std::vector<double>(n));
  //m by n vector is fully constructed, and ready to read!
  for(int i=0; input_wf && i<nbasis; i++)
  {
    for (unsigned int ir=0; input_wf  && ir<wf->size(); ir++)
      input_wf >> wavefunctions[i][ir];
  }
  if (!input_wf)
      throw std::runtime_error("improper data in the file!");
  return wavefunctions;
}
于 2012-07-16T22:47:37.057 回答
0
std::vector<std::vector<double> * > wavefunctions = *(new std::vector<std::vector<double>*>(m));

这在我看来很可疑。我相信你的意思是做两件事之一。

在堆栈上声明它并返回它的副本。

 std::vector<std::vector<double> * > wavefunctions;

在堆上声明它并从你的函数返回一个指针。(这使得调用者负责删除分配的内存。)

std::vector<std::vector<double> * > *wavefunctions = new std::vector<std::vector<double>*>(m);
于 2012-07-16T22:41:47.000 回答
0

首先,你为什么要维护一个指针向量?这样做几乎没有充分的理由(我想不出一个,但我不知道一切。)如果您需要存储指针,则存储智能指针。您正在否定向量为您管理内存的能力。

std::vector<std::vector<double> * > wavefunctions = *(new std::vector<std::vector<double>*>(m));

在这里,您new创建一个向量,立即取消引用它并将其复制到您的本地向量。那里有内存泄漏,因为new'd 向量(及其指针)丢失了,您只需复制它并将其丢弃。同样,将指针存储在向量中是一个坏主意,而且您的分配方法总是错误的。

只需使用 avector<vector<double> >并让向量为您管理动态内存(尽管最好对该主题进行更多研究,以便您了解代码在做什么。)

我什至有点犹豫要不要这么说,但是在使用向量来模拟锯齿状数组时可能会出现性能问题。问题是数据的局部性之一,但这仅适用于性能敏感代码中的紧密循环,并且有许多因素可能使这一点没有实际意义。

于 2012-07-16T23:25:06.177 回答