C ++引用传递

时间:2015-03-17 11:49:15

标签: 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;
}

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

2 个答案:

答案 0 :(得分:3)

您的setLeftsetRight功能引发了警钟。存储通过引用传递的对象的地址严重要求麻烦,因为调用者可能会破坏对象,然后您将留下LeftRight的悬空指针。

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


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

另一个选择是使用智能指针来跟踪对象的所有权,但是在执行此操作之前还有一些其他问题需要解决。

具体而言,treeNode目前不在Rule of Three之后。解决这个问题非常重要。至少disable copying,以便您不会意外地制作treeNode的副本(在您开始遵循三条规则之前行为不正常))。

使用智能指针类意味着你可以遵循零度规则而不是规则三,这样可以提供更清晰的代码(尽管如果你是C ++的新手,可能很难直接做到这一点,但是没有&# 39;除了SO),我知道任何好的在线教学资源。

答案 1 :(得分:0)

您正在使用临时值调用Treenode构造函数并存储在指向这些临时值的treenode指针中。 构造函数完成后,这些临时值消失了,在调用一个使用指向那些temps(toString)的指针的函数时,就会发生崩溃。

只要使用了树,您的设计就需要树项目的值,因为您只存储指向树中这些值的指针。 您可以更改设计以存储树中的treenode副本。