【问题标题】:C++ Strings In Class Becoming Empty after Construction类中的 C++ 字符串在构造后变为空
【发布时间】:2020-03-31 23:31:45
【问题描述】:

我正在创建一个程序,其中部分工作是将标记为 Client() 的类对象存储在二叉树中。 我使用

在 switch 语句中创建对象
Client newClient = Client (first, last, iD);
transactionsTree.Insert(newClient);

switch 语句处于读取数据的循环中,因此在执行此案例并且程序继续执行后,该类中的字符串将设置为空的 "" 字符串。我在逐步调试时发现了这一点,并且一旦该 case 块执行,字符串就会变为空。放入该类的任何其他数据都会保留,但这些字符串不会。即使我在 Client.h 文件中声明了这些字符串名称,它们在创建它的 switch case 之后仍然是空的。我创建上面显示的 newClient 的代码在 Transactions.cpp 中,transactionsTree 是 BSTree.cpp 的类对象,还有 Client.cpp,所有这些类共享一个连接,但我假设我的问题必须做以及我如何将对象插入二叉树。

下面是带有 switch 语句大小写的代码:

case 'O': // open an account
            {
                string first = list.front();
                list.pop();
                string last = list.front();
                list.pop();
                stringstream getiD(list.front()); // transfer string to int
                list.pop();
                int iD = 0;
                getiD >> iD; // transferring string to int

                if (transactionsTree.Retrieve(iD)) // if Client is already in tree, prints error message
                {
                    cout << "ERROR: Account " << iD << " is already open. Transaction refused." << endl;
                }
                else // else creates new Client
                {
                    Client newClient = Client (first, last, iD);
                    transactionsTree.Insert(newClient);
                }

                break;
            }

这是我对二叉树的插入方法:

void BSTree::Insert(Client &newClient)
{
    if (isEmpty())
    {
        Node *newNode = new Node(newClient);
        this->root = newNode;
    }
    else
        add(this->root, newClient);
}

BSTree::Node* BSTree::add(Node *node, Client &newClient) // helper function for Insert()
{
    if (node == nullptr)
        {
            Node *newNode = new Node(newClient);
            return newNode;
        }
    if (newClient.clientID < node->pClient->clientID)
        node->left = add(node->left, newClient);
    else
        node->right = add(node->right, newClient);
}

edit1:经过进一步检查,在标头或构造函数中声明的类中的字符串都不成立,尽管这里是字符串向量。我还有一个字符串数组,整个数组在 Client.cpp 的标头中声明,但是当我尝试从任何 Client 对象中打印出任何字符串时,它只会打印出一个地址。

edit2:我已将我的问题隔离到两个区域,一个是我尝试使用以下方法访问树中的客户端:

Client *ptrClient; // create pointer to access the Client once found
                        ptrClient = &transactionsTree.getClient(iD);

还有两个在我的二叉树类中的 getClient 方法中:

Client& BSTree::getClient(int id) // returns a Client object from the tree to process() in Transactions.cpp
{
    return getTheClient(this->root, id);
}

Client& BSTree::getTheClient(Node * node, int iD) // helper function for getClient that returns a Client object in the tree
{
// no need for the if condition of iD not being found because I check if the iD is in the tree before this function is executed
    if (node->pClient->clientID == iD)
    {
        cout << node->pClient->firstName << " PRINTED HERE~~~~~~~~~~~~~" << endl;
        return *node->pClient; // return client if found
    }
    if (iD < node->pClient->clientID)
        return getTheClient(node->left, iD);
    else
        return getTheClient(node->right, iD);
}

这些更新的信息是否有助于您帮助我解决我的问题?

【问题讨论】:

  • 我想我们需要一个minimal reproducible example 来给你一个 100% 正确的答案,这对未来的其他程序员很有用。
  • Client 是否有有效的复制构造函数和赋值运算符?
  • @TroubledProgrammer -- 我看到不是所有的 BSTree::add 的代码路径在我每次运行我的程序时都会返回一个值,这是什么意思? -- 你的函数是应该返回一个BSTree 指针。您是否在函数可以采用的所有路径中都这样做?你没有。因此,在if 语句之后程序的行为是未定义的。应该返回一个值的尾递归函数的框架类似于T foo(some_param) { ( if (whatever) { return a T; } { return foo(some_params); }——注意末尾的return
  • 我们需要看到的是A Minimal, Complete, and Verifiable Example (MCVE),所以我们知道Client是如何定义的,Node是如何定义的,以及它们是如何构造的,等等...这将有助于确定应用程序the Rule of Three(或五个或没有)。
  • 我理解,但理解是为了帮助您,特别是在处理实现 BST 存储节点的类时,我们无法验证它们是如何定义或构造的从几个代码片段中找出您的代码无法正常工作的原因。有时如果错误很明显可以解决,但有时如果问题取决于某些未显示的代码,则导致猜测是我们能做的最好的。 MCVE 还允许我们编译有问题的代码,并在编译器的帮助下解决您的问题。

标签: c++ string class switch-statement binary-tree


【解决方案1】:

我解决了我的问题,就是这两行:

Client newClient = Client (first, last, iD);
transactionsTree.Insert(newClient);

我改成:

Client *newClient = new Client (first, last, iD);
transactionsTree.Insert(*newClient);

这很重要,因为我在堆栈而不是堆中创建了一个新对象。

【讨论】:

  • 这可能确实解决了问题,但你这样做的方式会让人们感到困惑。大多数看到解决方案的人都会想,“伙计!你为什么要泄露内存?”考虑将void BSTree::Insert(Client &amp;newClient) 替换为void BSTree::Insert(Client * newClient) 并明确表明您在整个过程中传递了一个原始指针。更好的是,查看std::unique_ptr 以使对象的所有权超级明显..
  • @user4581301 谢谢,我可能会在上交之前进行调整,您能帮我解决另一个问题吗?我知道出了什么问题,但我不知道为什么。我的二叉树只是覆盖了根的叶子。这是它发生的功能
  • @user4581301BSTree::Node* BSTree::add(Node *node, Client &amp;newClient) // helper function for Insert() { if (node == nullptr) { Node *newNode = new Node(newClient); node = newNode; return newNode; } if (newClient.clientID &lt; node-&gt;pClient-&gt;clientID) return node-&gt;left = add(node-&gt;left, newClient); else return node-&gt;right = add(node-&gt;right, newClient); }
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-08
  • 2017-02-18
  • 2020-04-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多