填充向量的指针向量

时间:2012-07-16 22:32:15

标签: c++ memory vector new-operator

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

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 个答案:

答案 0 :(得分:2)

以下一行,

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

在您的案例中存在问题有两个原因 -

  1. 导致内存泄漏,因为new创建的对象被复制wavefunctions,然后指向它的指针丢失。这不是Java ......
  2. 它在向量中分配m个条目。后续push_back添加到m个条目,因此当您尝试访问wavefunctions[0]时,您实际访问的是在此行中创建的条目,而不是第一个要在该行中创建的条目for循环。
  3. 要解决此问题,请将行更改为

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

    reserve方法可确保您在push_back期间无法重新分配。

    作为最后一点,根据环境的不同,编译器可能会或者可能无法优化从函数返回时执行的向量的固有副本。当然,您可能希望了解有关r值引用(&&)的更多信息,或者只是按地址返回向量(即,作为类型vector<...> *的另一个参数并返回类型{{1} })。

答案 1 :(得分: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;
}

答案 2 :(得分: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);

答案 3 :(得分:0)

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

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

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

只需使用vector<vector<double> >并让向量为您管理动态内存(尽管最好多学习一下这个主题,以便了解您的代码正在做什么。)

我甚至有点犹豫,但是当使用向量来模拟锯齿状数组时,可以出现性能问题。问题是数据的局部性问题,但这只适用于性能敏感代码中的紧密循环,并且有许多因素可能会导致这一点无关紧要。