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();
...
有关这一点为何重要的进一步解释,请参见以下链接:
编辑:在代码中添加了一些打印语句。这个问题似乎是双重的
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;
};