【问题标题】:Class member to point to a specific node member of an STL list?类成员指向 STL 列表的特定节点成员?
【发布时间】:2015-07-26 23:34:46
【问题描述】:

如何将指向某人配偶姓名的指针存储为该人类的私有成员?

例如,假设我有以下代码:

#include <iostream>
#include <list>

using namespace std;

class person
{
    private:
        string name;
        string *spouse;

    public:
        void setName(string tempName) { name = tempName; }
        void setSpouse(string &tempSpouse) { spouse = &tempSpouse; } // ERROR HERE?

        string getName() { return name; }
        string getSpouse() { return spouse; } // ERROR HERE?
};

int main()
{
    person entry;
    list<person> personList;
    list<person>::iterator itr1, itr2;

    /* Adding two people/nodes to the linked list. */

    entry.setName("John Doe");

    personList.push_back(entry);

    entry.setName("Tina Doe");

    personList.push_back(entry);

    /* Attempting to assign Tina Doe as John Doe's spouse. */

    for (itr1 = personList.begin(); itr1 != personList.end(); itr1++)
    {
        if (itr1->getName() == "John Doe")
        {
            for (itr2 = personList.begin(); itr2 != personList.end(); itr2++)
            {
                if (itr2->getName() == "Tina Doe")
                {
                    itr1->setSpouse(itr2->getName()); // ERROR HERE?
                }
            }
        }
    }

    /* Displaying all Names with Spouses afterwards. */

    for (itr1 = personList.begin(); itr1 != personList.end(); itr1++)
    {
        cout << "Name: " << itr1->getName() << " | Spouse: " << itr1->getSpouse() << endl;
    }

    return 0;
}

我无法将配偶姓名的地址分配给班级中的指针成员。我已经在 cmets 中指出了我认为可能存在错误的位置。

您可以在这里查看代码和错误:https://ideone.com/4CXFnt

任何帮助将不胜感激。谢谢。

【问题讨论】:

  • 如果有其他我忽略的信息,请告诉我,我会立即编辑这篇文章。谢谢。
  • 考虑将std::list 替换为std::vectorstd::list 是一个双向链表,只有在真正必要时才使用它(中间经常插入和删除)。对于任何其他用途,它很慢。默认使用vector
  • @IlyaPopov 不幸的是,对于这个特定的程序,使用向量是不可能的。必须是链表,配偶成员必须包含指向配偶姓名记录的指针。
  • 啊,我明白了。如果它必须包含一个指向配偶的指针,那么列表确实是一个合适的选择。
  • @IlyaPopov 关于如何解决我的代码出现的错误,您还有其他建议吗?

标签: c++ pointers stl compiler-errors linked-list


【解决方案1】:

getName 返回一个临时的std::stringname 变量的副本),编译器试图避免您引用即将被删除的内存部分。此错误与列表无关 - 要修复它,您需要将副本存储在 spouse 变量中(这将导致在多个位置存储相同的数据)或在 getName 中返回引用。您还可以考虑创建另一个访问器(私有的),但它很难看。

我建议存储副本,但如果确实需要引用/指针,那么修改行就足够了:

    string getName() { return name; }
    string getSpouse() { return spouse; } // ERROR HERE?

    string& getName() { return name; }
    string getSpouse() { return *spouse; } // ERROR HERE?

但是,为了保持一致性,我建议:

    string& getName() { return name; }
    string& getSpouse() { return *spouse; } // ERROR HERE?

【讨论】:

  • 你能给我一个你的答案的代码示例吗?在这种特殊情况下,配偶成员必须包含指向配偶姓名记录的指针。
  • 很好的答案!谢谢。
  • 这很好,但不能修复itr1-&gt;setSpouse(itr2-&gt;getName());(或者我不明白)
  • @styko:它确实如此——因为get 方法现在返回一个引用,而set 接受了一个引用,所以引用了实际的spouse——因此没有编译错误。我并不是要声称这是解决这个问题的好方法——我只是在说明它按照预期的方式工作。我倾向于同意,尽管那里可能会出现 person 指针而不是 string
【解决方案2】:

你有两个问题。第一个很容易修复:getSpouse 没有返回正确的类型。你应该写

string getSpouse() { return *spouse; } // Derefencing the pointer and returning a string
// or
string* getSpouse() { return spouse; } // Returning the pointer

第二个问题更微妙。当您编写:itr2-&gt;getName() 时,您只有一个值(itr2->name 的 copy):您没有存储可以更改的变量,因此您无法进行引用给它。

没有简单的方法可以让类实例中的指针指向另一个实例的私有变量。我想你应该质疑你做事的方式,并创建一个指向 person 而不是名称的指针(记住指针很便宜,它们只是内存位置)。

class person
{
    private:
        string name;
        person *spouse;

    public:
        void setSpouse(person *_spouse) { spouse = _spouse; }
        person* getSpouse() { return spouse; } 
        string getSpouseName() { return spouse->getName(); }
};

这项工作,但仍然不安全:如果spouse 被破坏并尝试从person 访问它,您将遇到严重问题......(请注意,您与string 有同样的问题) .

那么解决方法是什么?好吧,如果您只想让B 成为A 的配偶,您可以先创建B,并在A 中使用构造函数进行引用。但是如果你想让B成为A的配偶,而A成为B的配偶,你必须使用上面的不安全技巧并小心,或者将配偶名单储存在课堂之外。

【讨论】:

    猜你喜欢
    • 2018-03-24
    • 2018-11-13
    • 1970-01-01
    • 2013-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多