C++ 引用传递

标签 c++ pointers reference

我已经使用 C# 大约一年了,最近一直在测试我对 C++ 严酷世界的耐心。

我正在尝试创建一个面向对象的二叉树。我已经逐步完成代码并阅读了 C++ 中引用参数的传递和 const 的使用,但无法弄清楚我正在做什么导致访问冲突错误。我已确保正确创建了结构并且代码按预期完成了 main 的第一行,但是调用 toString 似乎会导致错误,我无法弄清楚原因。

这是目前的代码:

// ExpressionCL.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

using namespace std;

template<class TData> class TreeNode
{

private:
    TData Data;
    const TreeNode<TData>* Left = nullptr;
    const TreeNode<TData>* Right = nullptr;

    void setData(TData data)
    {
        Data = data;
    }

public:
    TreeNode<TData>(TData data)
    {
        setData(data);
    }

    TreeNode<TData>(TData data, const TreeNode<TData>& leftNode, const TreeNode<TData>& rightNode)
    {
        setData(data);
        setLeft(leftNode);
        setRight(rightNode);
    }

    void setLeft(const TreeNode<TData>& leftNode)
    {
        Left = &leftNode;
    }

    void setRight(const TreeNode<TData>& rightNode)
    {
        Right = &rightNode;
    }

    TreeNode<TData> getLeft() const
    {
        if (hasLeft())
        {
            return Left;
        }
    }

    TreeNode<TData> getRight() const
    {
        if (hasRight())
        {
            return Right;
        }
    }

    TData getData() const
    {
        return Data;
    }

    bool hasLeft() const
    {
        if (Left != nullptr)
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    bool hasRight() const
    {
        if (Right != nullptr)
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    string toString() const
    {
        string treeString = "";
        if (hasLeft())
        {
            treeString += Left->toString();
        }
        treeString += to_string(Data);
        if (hasRight())
        {
            treeString += Right->toString();
        }
        return treeString;
    }
};

int _tmain(int argc, _TCHAR* argv[])
{
    TreeNode<int> IntTree(1, TreeNode<int>(1), TreeNode<int>(2));
    cout << IntTree.toString() << endl;
    return 0;
}

一些指导或进一步推荐的资源会很棒。

最佳答案

您的 setLeftsetRight 函数敲响了警钟。存储通过引用传递的对象的地址是很严重的自找麻烦,因为调用者可能会破坏该对象,然后您会留下 LeftRight 的悬垂指针.

事实上,这正是您所做的。您将临时对象传递给构造函数,将它们的地址存储在 LeftRight 中。然后调用 IntTree.toString(),它会尝试使用指向不再存在的对象的指针。


要解决此问题,您需要对节点使用手动生命周期管理。这意味着必须通过 new 创建节点。您可以选择使用原始指针(在这种情况下,您会仔细记录您的接口(interface),注意调用者应该调用 new,传入指针,而不是调用 delete 之后)。

另一种选择是使用智能指针来跟踪对象的所有权,但是在这样做之前您还有一些其他问题需要解决。

具体来说,treeNode 当前不遵循 Rule of Three .解决这个问题非常重要。至少,disable copying这样你就不会不小心复制了一个treeNode(在你开始遵循三规则之前它不会正常运行)。

使用智能指针类意味着您可以遵循零法则而不是三法则,这使得代码更加简洁(尽管如果您是 C++ 的新手,可能很难直接做到,但没有任何除了 SO,我还知道很好的在线教学资源)。

关于C++ 引用传递,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29098316/

相关文章:

linux - gcc中的大尺寸指针

c# - Visual Studio 添加控制台应用程序作为引用

visual-studio-2008 - 当我向解决方案中添加项目时,如何让 Visual Studio 自动添加引用?

c++ - Boost Zlib的解压缩在Windows上崩溃

C++ - union 函数调用会导致内存泄漏吗

c++ - 第一个元素的索引 > 到具有 STL::algorithm 的 vector 中的数字?

c++ - 回调函数和常规函数有什么区别?

objective-c - Objective-C 中的 @ 运算符是否与 C 中的 & 运算符相同?

c - 在这个 : &(Array[id])? 发送元素#id 的指针中是否需要 Parens

c++ - 使用引用指向节点的指针的函数删除链表中的节点?