带指针的函数
Posted
技术标签:
【中文标题】带指针的函数【英文标题】:Functions with pointers 【发布时间】:2011-04-01 17:17:24 【问题描述】:就在我以为我的指针向下时,看起来我还是有点困惑。我正在写 operator= 重载,所以我想释放内存然后分配新的。我正在处理一个四叉树类,其中每棵树都有一个指向根节点的指针,一个根节点有 4 个指向 4 个子节点的指针,每个节点都有 4 个子节点。所以 operator= 应该只复制另一棵树的根并返回它。所以在解除分配等之后,我开始想要分配新的内存和分配。所以我这样做:
root=new QtreeNode;
root=nodeCopier(*(source.root));
这是我的 nodeCopier 签名:
QNode nodeCopier(const QtreeNode & n)
QtreeNode tempNode;
//stuff
return tempNode;
然后我得到这个错误错误:
no matching function for call to
Qtree::nodeCopier(Qtree::QtreeNode* const&)
qtree.h:92: note: candidates are: Qtree::QtreeNode Quadtree::nodeCopier(const Qtree::QtreeNode&)
我该如何解决这个问题?
【问题讨论】:
你能发布你的班级声明QtreeNode
吗?
【参考方案1】:
去掉nodeCopier
的论点,这部分对我来说看起来不对..
root=new QtreeNode;
root=nodeCopier( /* ... */ );
nodeCopier
返回QNode
(基于您的return
语句可以从QtreeNode
隐式转换)但是从第一行我们可以将它分配给QtreeNode*
。或者更一般地说,您将非指针数量分配给指针。
看起来你可能想做:
*root = nodeCopier( /* ... */ );
根据此处的第二行和错误消息,我可以看到第二个问题。
root=nodeCopier(*(source.root));
Qtree::nodeCopier(Qtree::QtreeNode* const&)
qtree.h:92: note: candidates are:
Qtree::QtreeNode Quadtree::nodeCopier(const Qtree::QtreeNode&)
基于此,source.root
看起来像 QtreeNode**
,因为您使用 *
取消引用它并且该表达式显然产生了 QtreeNode*
。无论是那个还是root
都做了一些非常时髦的运算符重载。无论如何,您将QTreeNode*
传递给期望QTreeNode&
的函数;您应该使用**source.root
或(更好)重新评估source.root
是否需要为QtreeNode**
类型。 (我的猜测是没有。)
编辑: 我同意其他人所说的惯用 C++ 方法是创建一个复制构造函数。但是我想我的方法是帮助解释为什么它不能编译。我想为了帮助您弥合概念上的差距,最好通过更多 C 风格的指针操作进行一些练习...
【讨论】:
【参考方案2】:如果你传入一个指针,你不需要返回一个 QtreeNode,你应该这样做
root=new QtreeNode(); //declare a new QtreeNode
root=nodeCopier(&(source.root)); //pass a pointer to root into nodeCopier
void nodeCopier(const QtreeNode* n)
QtreeNode tempNode = new QtreeNode(); //declare a local QtreeNode
//stuff
*n = tempNode; //dereference root pointer and assign tempnode
delete(tempNode); //Delete tempNode to prevent memory Leak
希望对你有帮助,
埃蒙
【讨论】:
这里仍然出现错误。n
不是指针,那你为什么要在最后一行取消引用呢?
不好意思,看我最新的编辑,需要在函数参数中放*来传入一个指针,调用函数时使用&。 * 在变量声明之后表示将此变量声明为指针,* 在变量名之前表示取消引用此指针,& 表示使用传递此变量的内存位置【参考方案3】:
您在包含的类上提到了 operator= 重载 指针。所以让我们上一层,看看它是什么:我怀疑 你真正需要的是一个复制构造函数(首先),然后使用 交换成语。比如:
QtreeNode::QtreeNode( QtreeNode const& other )
: north( other.north == NULL ? NULL : new QtreeNode( *other.north ) )
, east( other.east == NULL ? NULL : new QtreeNode( *other.east) )
, south( other.south == NULL ? NULL : new QtreeNode( *other.south) )
, west( other.west == NULL ? NULL : new QtreeNode( *other.west) )
QtreeNode& QtreeNode::operator=( QtreeNode const& other )
QtreeNode tmp( other );
swap( tmp );
return *this;
void QtreeNode::swap( QtreeNode& other )
std::swap( north, other.north );
std::swap( east, other.east );
std::swap( south, other.south );
std::swap( west, other.west );
您绝对不想做的是删除之前的现有节点 您已成功复制新树;这是肯定的 未定义的行为——通常以双重删除的形式。
而且你不需要复制的特殊功能;复制构造函数 以上是递归的,会为你处理一切。
【讨论】:
【参考方案4】:看起来发帖人的问题是实现复制分配(operator=)。我建议您根据复制构造函数来实现您的 operator=,即复制和交换。看看this example in SO。看看 operator= 是如何在那里实现的。
如果您已经实现了复制构造函数,这几乎可以免费为您提供 operator=,因此您不需要仅仅为了复制分配而实现这个“nodeCopier”。
【讨论】:
【参考方案5】:当在指针上指定“const”时,它可以应用于一两件事。指针可以是常量(即指针包含的地址不能改变),或者该地址指向的值可以是常量,或者两者都可以是常量。请参阅here 进行讨论。
const QtreeNode * p1 = <value>; // non-constant pointer to constant value
QtreeNode * const p2 = <value>; // constant pointer to non-constant value
const QtreeNode * const p3 = <value>; // constant pointer to constant value
如您的问题所示,nodeCopier 函数引用了一个常量 QtreeNode。从错误消息中我们可以看到编译器正在寻找一个 nodeCopier,它引用一个指向 QtreeNode 的常量指针
Qtree::nodeCopier(Qtree::QtreeNode* const&)
换句话说,*(source.root) 的类型与 nodeCopier 函数的形式参数的类型不匹配。您可以通过更改 nodeCopier 的定义或更改传递给 nodeCopier 调用的实际参数来解决此问题。
【讨论】:
以上是关于带指针的函数的主要内容,如果未能解决你的问题,请参考以下文章