【问题标题】:Class creating multiple objects of another class at the same memory location (C++)类在同一内存位置创建另一个类的多个对象(C++)
【发布时间】:2013-08-02 19:02:01
【问题描述】:

所以,我有一个包含另一个类的向量的类。每当我尝试将新对象推入此向量时,它每次都会在相同的内存位置创建该对象。

(希望)相关代码:

class FSM{
    private:
        std::vector<Node> nodeList;
        int cap;
        int obs;
        int topNode;

    public:
        FSM(int nodeCap, int numObs){
            cap = nodeCap;
            obs = numObs;
            topNode = -1;
        }

        bool addNode(){
            if (isFull()) return false;
            nodeList.push_back(Node(obs));
            topNode++;
            return true;
        }

现在,如果我在我的主函数中创建一个独立的 Node 对象并计算 &node,我会得到不同的内存位置。但是在 FSM 类中创建的总是相同的。此外,如果我更改 FSM 类存储的节点之一中的任何内容,它会更改所有节点。我不知道发生了什么。

编辑:根据要求,这里是 Node 类。只是发布整个事情,不确定什么是相关的。

class Node{
    private:
        std::vector<int> connects;
        int action;

    public:
        Node(int numObs){
            for(int i = 0; i < numObs; i++){
                connects.push_back(-1);
            }
            srand(time(NULL));
        }

        void setConnections(std::vector<int> newVec){
            for (int i = 0; i < connects.size(); i++){
                connects[i] = newVec[i];
            }
        }

        int getConnection(int index){
            return connects[index];
        }

        std::vector<int> getConnectionList(){
            return connects;
        }

        void setAction(int act){
            action = act;
        }

        int getAction(){
            return action;
        }

        void setRandomConnections(int numNodes){
            for (int i = 0; i < connects.size(); i++){
                connects[i] = rand() % numNodes;
            }
        }
};

编辑第二个:这是我的主要工作。

int main(){
FSM myFSM(5, 3);
while (!myFSM.isFull()){
    myFSM.addNode();
    std::cout << &myFSM.getTopNode(); // getTopNode() returns the most recent
                                              // node.
}
}

【问题讨论】:

  • 我们能看到 Node 类吗?
  • 那么您是否将多个节点推送到向量?或者你只是重新运行你的程序几次?
  • 我们可以看到获取Node 以显示其地址的代码吗?我怀疑这段代码是问题所在。
  • 如果 getTopNode 做我认为的那样,你正在打印一个临时对象的地址(也就是顶部节点的 copy,而不是顶部节点本身)。所以那个代码是没有意义的。
  • 显示可以复制、粘贴、编译和运行的代码。重建所有缺失的小片段不是任何人的想法。

标签: c++


【解决方案1】:

如果 getTopNode 做了我认为的那样,那么您正在打印一个临时对象的地址(也就是顶部节点的副本,而不是顶部节点本身)。所以那个代码是没有意义的。

Here我已经实现了FSM中节点位置的打印功能:

void printNodeLocations()
{
    for(Node& n : nodeList) { std::cout << &n << std::endl; }
}

我得到了不同的结果:

0x8ad3018
0x8ad301c

编辑:我无法重现您声称更改一个节点会更改所有节点的说法。 See updated code

【讨论】:

  • 嗯...让我看看。我想我可能知道节点更改的问题,但我想你就在这里。
  • @MRoush 我添加了一个更新代码示例,我在其中更改了一个节点的值。其他节点不受影响。
  • 是的,这就是问题所在。我认为另一个问题也是打印错误。谢谢!
【解决方案2】:

这一行:

std::cout << &myFSM.getTopNode();

可能会打印临时对象的地址,而不是向量中的实际对象。如果您不是按引用返回而是按值返回,这将是正确的。

所以如果每次都在同一个位置创建临时的,这并不奇怪,因为在临时死后,它在内存中的位置可以在以后再次使用。

为了获取实际对象而不是它的副本,getTopNode() 需要这样做:

Node& FSM::getTopNode()
{
    if (nodeList.empty()) {
        // Up to you how to handle this error.
    }
    return nodeList.back();
}

当然,如果你当前的 getTopNode() 实现实际上已经返回了一个指针:

Node* FSM::getTopNode()

那么你的问题是你打印出指针的地址而不是指针本身。在这种情况下,您应该打印:

std::cout << myFSM.getTopNode();

【讨论】:

  • 是的,但它没有解释原始问题中的这一断言:“如果我更改 FSM 类存储的节点之一中的任何内容,它会为所有节点更改它。”跨度>
  • 它没有。您不能使用临时地址。
  • @n.m.你可以用一些编译器来做到这一点。
【解决方案3】:

没有发生与你类似的事情。

#include <iostream>
#include <vector>

class Node{
    private:
        std::vector<int> connects;
        int action;

    public:
        Node(int num){
            for(int i = 0; i < num; i++){
                connects.push_back(i);
            }

        }
    std::vector<int> getConn()
    {
        return connects;
    }
};

class FSM{
    private:
        std::vector<Node> nodeList;
    public:
        FSM(){}
    void addNode(int size){
        Node l(size);
        std::cout<<"temp_address "<<&l<<"\n";   
        nodeList.push_back(l);//use of default copy constructor
    }
    void printList(){
        std::vector<int> p;
        for (int i=0; i<nodeList.size(); i++)
        {
            std::cout<<"Node_arr_num "<<i<<" mem_address "<<&nodeList[i]<<"\nConnections:";
            p=nodeList[i].getConn();
            for (int j=0; j<p.size(); j++)
                std::cout<<" "<<p[j];   
            std::cout<<"\n";
        }
    }
};

int main()
{
FSM f;
f.addNode(5);
f.addNode(10);
f.addNode(3);
f.printList();
return 0;
}

Result:

temp_address 0xbfea7660
temp_address 0xbfea7660
temp_address 0xbfea7660
Node_arr_num 0 mem_address 0x8dab098
Connections: 0 1 2 3 4
Node_arr_num 1 mem_address 0x8dab0a8
Connections: 0 1 2 3 4 5 6 7 8 9
Node_arr_num 2 mem_address 0x8dab0b8
Connections: 0 1 2

当您的应用程序增长时,请小心添加节点。如果Node 更复杂(包含动态分配内存的字段),则必须使用类Node 的显式复制构造函数复制临时l 对象(或您的Node(obs))。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-23
    • 2019-07-29
    • 2011-06-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多