从另一个类返回类对象指针

时间:2016-10-26 20:40:50

标签: c++ class pointers

我难以用文字解释问题。但我在一个最小的例子中复制了我的问题。 基本上我有一个主类,持有不同类对象的向量。 这个主类有一个成员函数,它创建一个对象,将它添加到向量中,并返回一个指向向量中新对象的指针。 然后,当我尝试从返回的指针访问对象的值时,这些值就像从未设置过一样。

以下是最小示例的代码:

修改

有些人指出我在成员函数中有value = value。 这显然是一个错误,我已编辑为_value = value

#include <iostream>
#include <vector>

class MySecondaryClass
{
public:
    MySecondaryClass(int aValue) { _aValue = aValue; }
    ~MySecondaryClass() {}
    int _aValue;
};

class MyMainClass
{
private:
    std::vector<MySecondaryClass> _secClassVec;
public:
    MyMainClass() {}
    ~MyMainClass(){}

    MySecondaryClass* addNewSecClass(int aValue) { 
        MySecondaryClass newSecClass(aValue);
        _secClassVec.push_back(newSecClass);
        return &_secClassVec[_secClassVec.size() - 1];
    }
};


int main() {

    MyMainClass mainObject;
    MySecondaryClass* secObject1_ptr = mainObject.addNewSecClass(1);
    MySecondaryClass* secObject2_ptr = mainObject.addNewSecClass(2);
    MySecondaryClass* secObject3_ptr = mainObject.addNewSecClass(3);

    std::cout << secObject1_ptr->_aValue << std::endl;
    std::cout << secObject2_ptr->_aValue << std::endl;
    std::cout << secObject3_ptr->_aValue << std::endl;

    return 0;
}

输出:

-572662307
-572662307
3

预期输出为:

1
2
3

有人可以解释我在这里做错了吗?

3 个答案:

答案 0 :(得分:1)

将构造函数参数命名为无法在构造函数体中隐藏您的成员,并开始使用initialzier列表:

MySecondaryClass(int aValue_) : aValue(aValue_)
{ }

还要记住,推回向量可能会使迭代器(以及指向其元素的指针)失效。

好吧,既然你编辑了你的问题。我只能建议你像指针一样返回表现的代理对象。

class MySecondaryClassPtr
{
  MyMainClass& mmc_;
  std::size_t  pos_;

  public:
  MySecondaryClassPtr(MyMainClass& mmc, std::size_t pos) :
   msc_(msc), pos_(pos)
  {}

  MySecondaryClass& operator*()  { return mmc_._secClassVec[pos_]; }
  MySecondaryClass* operator->() { return &mmc_._secClassVec[pos_]; }  

};

这个&#34;智能指针&#34;代理对象与MyMainClass对象的生命周期相关联,而不是向量的内部存储。

答案 1 :(得分:1)

第一个问题是在构造函数中:

import numpy as np
board=np.zeros((8,8))
board[0:,0]=1

它的作用是将参数aValue赋给自身,即不设置类的aValue属性。这可以通过以下任一方法解决:

MySecondaryClass(int aValue) { aValue = aValue; }

MySecondaryClass(int aValue) { this->aValue = aValue; }

但总的来说,这就是为什么不建议将参数命名为与属性相同的原因。

第二个问题是,呼叫:

MySecondaryClass(int aValue): aValue(aValue) {}

可能使分配给MySecondaryClass* secObject3_ptr = mainObject.addNewSecClass(3); secObject1_ptr的内存无效(如果向量调整大小) - 基本上每次调用secObject2_ptr都可能使先前返回的指针无效(从技术上讲,它是未定义的行为)。

修改

要回答评论问题:如果要将实际对象存储在类中并访问它们,则需要通过索引以不同方式执行,或者在某些情况下,您可以按ID保留映射,具体取决于你需要。但是你通常无法保持指向不断变化的数据结构的指针。

一种可能性:

mainObject.addNewSecClass()

但是,如果只添加到矢量,这也只能起作用。删除也会在删除项目后使索引无效。

另一种可能性是动态分配并仅将指针保留在向量中 - 然后在添加项目时原始对象地址不会改变。但随后需要管理生命周期,复制构造等,这可以通过使用智能指针(例如shared_ptr)进行一定程度的缓解。

答案 2 :(得分:0)

当你推入一个向量时,它必须为新元素分配内存。

此分配需求可能无法在内存中当前位于内存中的位置处满足,因此向量必须为其他内容的整个内容分配连续内存,移动旧内容,添加新内容并释放以前分配的块。

因此,每次更改矢量时,指向内存的指针都会变为无效。