C++ 为什么我的代码没有设置变量?

C++ 为什么我的代码没有设置变量?,c++,g++,C++,G++,队列的目的是存储指向T类型对象的指针。当我遍历各种数据结构时,队列用于在队列上推送和弹出对象 队列工作正常,但以下行除外: out = t->payload; (底部四行) out从不将值更改为t->payload中的值。在调试器中查看它,我可以看到t->payload设置正确,但是没有为out分配t->payload中的值。有人能告诉我发生了什么事吗 template<typename T> class Queue { private: struct node

队列的目的是存储指向
T
类型对象的指针。当我遍历各种数据结构时,队列用于在队列上推送和弹出对象

队列工作正常,但以下行除外:

out = t->payload;
(底部四行)

out从不将值更改为
t->payload
中的值。在调试器中查看它,我可以看到
t->payload
设置正确,但是没有为out分配
t->payload
中的值。有人能告诉我发生了什么事吗

template<typename T>
class Queue
{
private:
    struct node
    {
        T           *payload;
        struct node *next;
    };
    node *head;
    node *tail;
public:
    Queue()
    {
            head = new node;
        tail = new node;
        head->next = tail;
        tail->next = tail;
    }
        ...
    void push(T *payload)
    {
        node *newNode;
                node *temp;
        newNode = new node;
        temp = head->next;
        head->next = newNode;
        newNode->next = temp;
        newNode->payload = payload;
    }
    bool pop(T *out)
    {
        node *t;
        node *x;
        t = head;
        x = head;
        if(t == tail)
        {
            return false;  //already empty
        }
        while(t->next != tail)
        {
            x = t;
            t = t->next;
        }
        x->next = tail;
        out = t->payload;
        delete t;
        return true;
    }
}
模板
类队列
{
私人:
结构节点
{
T*有效载荷;
结构节点*下一步;
};
节点*头;
节点*尾部;
公众:
队列()
{
头=新节点;
tail=新节点;
头部->下一个=尾部;
尾部->下一步=尾部;
}
...
无效推力(T*有效载荷)
{
节点*新节点;
节点*温度;
newNode=新节点;
温度=头部->下一步;
head->next=newNode;
newNode->next=temp;
新节点->有效载荷=有效载荷;
}
bool pop(T*out)
{
节点*t;
节点*x;
t=头部;
x=头部;
if(t==tail)
{
返回false;//已为空
}
while(t->next!=尾部)
{
x=t;
t=t->next;
}
x->next=尾部;
out=t->payload;
删除t;
返回true;
}
}

创建新对象时,尝试添加一些括号

像这样:

head = new node();
tail = new node();
...
有关这一点为何重要的进一步解释,请参见以下链接:

编辑:在代码中添加了一些打印语句。这个问题似乎是双重的

  • 在push中,不要将newNode->payload设置为payload,而是尝试将其设置为newint(*payload)。这样将复制该值
  • 在pop的末尾,您将out的地址设置为t->payload,但t随后被删除,因此out不指向任何内容。而是如上所述复制该值
  • 如果你纠正这两件事,它似乎是有效的

    编辑2:将其作为参考实施

    bool pop(T &out)
    {
        node *t;
        node *x;
        t = head;
        x = head;
        if(t == tail)
        {
            return false;  //already empty
        }
        while(t->next != tail)
        {   
            x = t;
            t = t->next;
        }
        x->next = tail;
        out = *(t->payload);
        delete t;
        return true;
    }
    

    您正在将一个T*复制到一个T*,但目标是一个函数参数,它总是“in”。使用函数结果,或T**out或T*&out。

    严格来说,我无法重现您的错误:
    out
    正在设置为
    T->payload
    的值。。。在功能范围内

    您可以按值传入指针
    out
    。函数修改指针
    out
    ,它是一个局部变量,而不是调用函数时指向的对象,也不是作为变量存在于调用代码中的指针

    out=t->有效载荷

    这就是你问题的根源。您正在断开传递给函数的参数之间的链接。您的参数
    out
    是指针。如果你想使用这个范例(注意:这不是最好的主意),你永远不应该改变
    out
    。您应该改为通过更改
    out
    的内容

    *out = *(t->payload);
    
    以上有两个关键问题。如果
    out
    t->payload
    为空指针,则会发出咯咯声。您可以通过传递引用而不是指针来解决前一个问题。如果这样做,那么应该使用
    out=*(t->payload)
    。这并不能解决空负载的问题。您可以通过确保在添加节点时有效负载始终为非null来修复此问题


    然而,一个问题仍然存在。例如,如果该有效负载指针被删除,使解引用无效,该怎么办?使用指针总是有点问题。

    请注意,如果容器不强制客户端上的指针类型,那么它会更好。下面给出的非常简单的示例避免了签名中的显式星号(*)。因此,用户是否信任具有普通类型或指针类型的管理员是开放的。无论哪种方式,数据都只是简单地复制到“keep”实例变量中或从中复制出来。如果她决定使用指针,很好,但是分配和释放动态内存的责任在于她

    template<typename T>
    class Keeper {
    public:
      Keeper() : keeping(false){}
      virtual ~Keeper(){}
      void push( T & payload ){
        if( keeping ) throw "I'm busy";
        keeping = true;
        keep = payload;
      }
      bool pop( T & payload ){
        if( ! keeping ) return false;
        keeping = false;
        payload = keep;
        return true;
      }
    private:
      bool keeping;
      T keep;
    };
    
    模板
    班长{
    公众:
    Keeper():保留(false){}
    虚拟~Keeper(){}
    无效推力(T和有效载荷){
    如果(保持)抛出“我很忙”;
    保持真实;
    保持=有效载荷;
    }
    bool pop(T和有效载荷){
    如果(!keing)返回false;
    保留=错误;
    有效载荷=保持;
    返回true;
    }
    私人:
    布尔保持;
    不保持;
    };
    
    如何使代码美观。这太糟糕了。请参阅使用
    标记。我认为这里的问题在于删除t;在pop()中,因为它将调用默认的析构函数,该析构函数将调用成员上的析构函数。。这意味着out指向无效内存。。我的建议是:要么将有效负载作为引用而不是指针,因为它无论如何都不会改变。。或者为您的结构实现一个析构函数,该析构函数不删除有效负载,但将其设置为null ptr,这意味着其他人(谁?)负责删除。此问题的原因有十几行。感谢您的建议。我将来会这样做的。我添加了括号,但out仍然没有设置为t->payload值。请检查以上两个建议,它们应该可以解决您的问题;)请注意,建议1。这是一个设计决策。您想获得推送到队列上的对象的所有权,或者不想。重要的是,若你们不拥有所有权(这是有道理的),我建议你们实现有效负载作为参考。这也意味着你需要为你的负载在其他地方调用delete,否则你就有内存泄漏。1中给出的建议是有效的,但这不是我想要做的。我不想拥有所有权。你有一个如何实现它的例子作为参考吗?凯格曼:是的,同意。user758362:我已经在上面的参考中包含了一个如何实现它的示例。记得换t
    *out = *(t->payload);
    
    template<typename T>
    class Keeper {
    public:
      Keeper() : keeping(false){}
      virtual ~Keeper(){}
      void push( T & payload ){
        if( keeping ) throw "I'm busy";
        keeping = true;
        keep = payload;
      }
      bool pop( T & payload ){
        if( ! keeping ) return false;
        keeping = false;
        payload = keep;
        return true;
      }
    private:
      bool keeping;
      T keep;
    };