1

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

(希望)相关代码:

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.
}
}
4

3 回答 3

4

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

在这里,我为 FSM 中节点的位置实现了打印功能:

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

我得到了不同的预期:

0x8ad3018
0x8ad301c

编辑:我无法重现您声称更改一个节点会更改所有节点的说法。查看更新的代码

于 2013-08-02T19:35:06.240 回答
1

这一行:

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();
于 2013-08-02T19:09:41.260 回答
0

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

#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;
}

结果:

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

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

于 2013-08-02T20:00:34.640 回答