std::function 调用后类成员地址发生变化

问题描述 投票:0回答:1

我正在尝试实现两个类,如下面的代码所示,类 A 是更通用的母类,而类 B 是一个专门的子类,它自己声明从第一个类继承的 std::function 。

#include<vector>
#include<iostream>
#include<functional>

struct double_vec
{
  std::vector<double> p;
  std::vector<double> v;
};

typedef std::function<void ()> i_function;

class A
{
  public:
  A(){};
  A(std::vector<double_vec*> vec, i_function p_function, i_function v_function)
  {
    this->m_vectors = vec;
    this->m_function = p_function;
  };

  void apply()
  {
    std::cout << "address after function call: " << &m_vectors << std::endl;
    m_function();
  };

  protected:

  i_function m_function;
  std::vector<double_vec*> m_vectors;
};

class B: public A
{
  public:
  B(std::vector<double_vec*> vec)
  {
    this->m_vectors = vec;

    load_functions();
  };

  private:
  void load_functions()
  {
    m_function = [&]()
    {
      std::cout << "address after function call: " << &m_vectors << std::endl;
    };
  };
};

int main()
{

  std::vector<std::vector<double_vec>> vectors;

  std::vector<B> b;

  for(int i=0; i<1; ++i)
  {
    std::vector<double_vec> temp;
    std::vector<double_vec*> reference_vector;

    temp.resize(10);
    for(int i=0; i<10; ++i)
    { 
      temp.at(i).p.resize(10,1);
      temp.at(i).v.resize(10,3);
    }

    vectors.push_back(temp);
    
    for(int i=0; i<10; ++i)
      reference_vector.push_back(&vectors.back().at(i));

    B temp_b(reference_vector);
    b.push_back(temp_b);
  }

  b.front().apply();
}

这是我的输出:

address before function call: 0x55a934dc2320 
address after function call: 0x7ffc284c1130

当我尝试使用 lambda 从子类中声明的函数访问向量时,我注意到存储的数据不正确,经过进一步分析,类成员的地址在函数调用后发生了变化。 随着 m_vectors 的地址发生变化,它不再指向重要数据,并且访问的数据未定义。

当尝试用最少的代码在代码上重现问题时,我注意到除非我创建了要存储的数据的向量(主函数中的变量向量)和/或所述类的向量(主函数中的 b)函数)问题没有出现。

就像使用单个

std::vector<double_vec>
和 B 类的单个变量时发生的情况一样,我预计类成员
m_vectors
的地址不会改变。 我需要地址不改变才能访问存储的信息

我尝试使用

[this]()
[&,this]()
作为 lambda,但都没有改变结果

使用虚方法而不是 std::function 声明函数可以使事情正常工作,但是有一个子类以与 B 类似的方式声明,我需要使用

std::function
来代替,所以这不是一个好的解决方案。

我不确定问题出在哪里,所以如果有人可以向我解释发生了什么,我会很高兴。

c++ inheritance stdvector std-function
1个回答
0
投票

这条线有问题:

reference_vector.push_back(&vectors.back().at(i));

它将导致reference_vector中的

悬空指针
。当您不断将更多对象推入
vectors
时,最终
capacity
将填满,并且必须重新分配其内部数组,这会将现有对象重新定位到新的内存地址,从而使您已推入
reference_vector 的指针无效
.

为了避免这种情况,您需要在进入外循环之前使用

vectors.reserve()

© www.soinside.com 2019 - 2024. All rights reserved.