带指针的函数

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 调用的实际参数来解决此问题。

【讨论】:

以上是关于带指针的函数的主要内容,如果未能解决你的问题,请参考以下文章

带/不带指针的函数原型使用区别

不带星号的函数指针参数

带向量的函数指针

带指针的函数

带指针的字符串数组函数

带括号的三元表达式在 C 中的函数指针声明中返回函数名称的基本原理