【问题标题】:C++ Losing Template DataC++ 丢失模板数据
【发布时间】:2013-06-06 17:51:04
【问题描述】:

我不认为自己在 C++ 方面知识渊博,但我很难理解这个概念。所以我有一个类,它包含一些模板数据类型和一个双精度。我希望 m_data 变量是通用的,但现在我只使用无符号整数进行测试。当我使用指向无符号整数的指针调用函数 SetData() 时,我丢失了指针指向的信息。当我超出范围时会发生这种情况,所以我觉得我需要对其进行深层复制......

我尝试了许多不同的构造函数和赋值运算符,但我仍然丢失了信息......我觉得我在这里遗漏了一些关于模板的明显内容。如果有人能指出我为什么会丢失数据的正确方向,我将不胜感激。

一小段代码:

template<typename T>
class PointNode {

 public:

  PointNode(double p){ m_point = p;}
  ~PointNode();

 void SetData(T  * data);
 T * GetData() const;

  private:

   double m_point;
   T *m_data;

 };

template<typename T>
void PointNode::SetData(T * data)
{
  m_data = data;
}

template<typename T>
T * PointNode::GetData()
{
  return m_Data;
}

确定更多信息。这个类被存储在另一个类成员的映射中。这里有一点。

 template<typename T>
class AuMathPointTreeT
{

  public:

  //Member Variables 

  double m_dTolerance;  

  unsigned int m_cPoint;         


  map<VectorKey, PointNode<T> > m_tree; /*map posing as a tree */

  typename map<VectorKey, PointNode<T> >::iterator iter;   /* iterator  */
  pair< typename map<VectorKey, PointNode<T> >::iterator, bool > return_val;

  /* Tree methods */

  //constructor
  AuMathPointTreeT(double tol);

 ...
};

在另一个程序中,我正在使用这个类,创建节点并像这样设置模板数据

if (node = pnttree.AddPoint(point) )
{
    unsigned int * data = new unsigned int();
    *data = pntCount;
    node->SetData(data);
    ++pntCount;
}

更新:好的,发现了问题的罪魁祸首,并希望就如何处理它提出建议。当我将一个节点插入到映射类中时,会在该过程中调用一些函数,并且我会丢失指向新分配的节点类对象的原始指针。这就是我正在做的事情。

template<typename T>
PointNode<T> * AuMathPointTreeT<T>::
AddPoint(double point)
{
  PointNode<T> * prNode = MakeNode(point);

  m_cPoint++;

  return prNode;
} 

template<typename T>
PointNode<T> *  AuMathPointTreeT<T>::
MakeNode(double point)
{
  PointNode<T> * prNode = new PointNode<T>;

    //set the contents for the node just performs a few calcs on the values

  prNode->SetNode(point, m_dTolerance);


  //Create the key class using the 
  VectorKey key(point, m_dTolerance);

  //Store the key,node as a pair for easy access 
  return_val = m_tree.insert( pair<VectorKey, PointNode<T> >(key, *prNode) );
  if (return_val.second == false)
    prNode = NULL;

  unsigned int * test = new unsigned int;
  *test = 55;
  prNode->SetData(test);  //if call this here its no longer the right pointer 

  return prNode;
}

所以看了这个......我真的还是想返回一个指针并使用它。但也许迭代器被 return_val 持有?我也对各个方面的建议持开放态度。对不起,这个问题一团糟:\

【问题讨论】:

  • 为什么你的m_data 是T*,而不是T?
  • 我希望它是指向数据的指针,这不可能吗?
  • 请向我们展示你是如何使用你的班级的。
  • 当然有可能,就是不明白为什么
  • 请显示一个使用这个类的代码,因为我觉得这个代码很好

标签: c++ templates pointers generic-programming


【解决方案1】:

我认为这与模板的使用无关。一旦局部变量超出范围,它在堆栈上的位置可能会被其他数据覆盖。

如果您希望模板类实例比其地址传递给 SetData 的局部变量更有效,您应该考虑在堆而不是堆栈上分配数据。无论哪种方式,我都建议用适当的智能指针替换原始 m_data 指针。例如,在模板类及其客户端代码中使用 shared_ptr 应该可以减少数据复制量,同时确保无论原始数据变量是否在范围内,数据都保持有效。

【讨论】:

  • 我不能使用智能指针或 shared_ptr :( C++ 11 中什么都没有。
  • 您添加的最后一个代码 sn-p 显示 pntCount 在用于设置数据后立即更新。您是否意识到,通过使用指向数据的指针,您将指向修改后的值(即 pntCount++ 之后)而不是原始值?
  • 再次抱歉,我没有准确地添加我的代码中的内容,我做了 unsigned int * data = new unsigned int() 后跟 *data = pntCount。
  • @Odub:您始终可以使用 Boost 或自己实现一个。所以,你可以同时使用智能指针和shared_ptr ;)
  • 好的,所以最后你是问题的终结者。我确实失去了对我的 Node.js 的正确引用。我猜在插入后,我最初创建的指针指向对象的旧副本。谢谢!
【解决方案2】:

如果你想要一个深拷贝,你必须使用 T 而不是 T*,或者你必须使用 T* 进行动态内存分配(但这有点矫枉过正)并且会带来类似的结果。

如果你真的想要指针的节点,那就是当你使用你的节点时。

示例:

int number = 5;
Node<int*> oneNode(&number);  // number will die at end of scope
Node<int> anotherNode(number); //anotherNode can be used without risk

【讨论】:

    【解决方案3】:

    由于构造函数,您的代码将无法编译

    PointNode(double p){ m_point = p;}
    

    m_point 是 const,你必须将它写入初始化列表:

    PointNode(double p) : m_point(p) {}
    

    【讨论】:

    • 是的,对不起,这只是我为此写的一个存根,一切都编译得很好。这是一个运行时问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多