【问题标题】:Vector of object pointers does not seem to perform as intended in C++对象指针向量在 C++ 中似乎没有按预期执行
【发布时间】:2011-03-10 14:15:41
【问题描述】:

我已经关注了很长时间,但这是我第一次提出问题。简而言之,问题是; vector<Student*> studentvector 是一个对象指针向量,似乎将学生信息推回为 student ;但是当我打印以查看向量中的第一个是否按预期执行时,我看到它总是用新来的学生信息更新第一条记录,尽管studentvector.size() 没有问题它将记录推回向量我打了多少次addStudent(...) 但它用最后一个学生的信息填充了所有向量。在不使用智能指针或高级东西的情况下,如何在此框架内成功地用正确的信息填充向量?

对不起,如果我对我的问题含糊不清。您可以引导我提供理解问题所必需的内容。提前致谢。

addStudent(const string alias, const string name) throw(StudentException)
{
Student* student = new Student(alias, name)
studentvector.push_back(student);
cout << studentvector.front() << endl;
}

那是Student的实现;

#include "Student.h"

string *Alias;
string *Name;


Student::Student(string alias)
{
    Alias = new string(alias);
}

Student::Student(string alias, string name)
{
    Alias = new string(alias);
    Name = new string(name);
}

Student::~Student()
{
    delete Alias;
    delete Name;
}

const string& Student::getAlias() const
{
    return *Alias;
}

void Student::setAlias(const string& alias)
{
    *Alias = alias;
}

const string& Student::getName() const
{
    return *Name;
}

void Student::setName(const string& name)
{
    *Name = name;
}

考虑别名未保留。

【问题讨论】:

  • 您能否添加一个示例来说明您如何访问 studentvector?
  • 1) 不要使用异常规范 2) 学习使用调试器
  • 我确信您在上面编写的代码是正确的,并且不会导致您描述的问题。然而,还有许多其他地方可以,比如 Student 类,operator&lt;&lt;(std::ostream&amp;, const Student *)(或者你真的只打印地址,因为上面的代码在没有该运算符的情况下),声明 studentvector 的方式和我可能忘记了一些。您需要提供更多背景信息才能获得更多诊断信息。
  • (给未来的读者注意:这里的许多答案和 cmets 都是在 afu 提供实现 Student 的代码之前编写的,这正是问题所在。这就是为什么他们未能解决实际问题问题。)
  • @Gareth McCaughan 感谢您的澄清:)

标签: c++ pointers object vector


【解决方案1】:

哇!这是您的问题 - Student 类型的所有对象都使用相同的 global 指针:

string *Alias;
string *Name;

让这两个成为你班级的成员


class Student
{
private:
    string *Alias;
    string *Name;
//..
}; 

编辑: 另外,我不认为使用指向std::string 的指针是个好主意,我建议你这样使用:

班级学生 { 私人的: 字符串别名; 字符串名称; //.. };

【讨论】:

  • 成员不是堆栈对象。它们占用的内存是其完整对象内存的一部分。
  • 谢谢它的工作;但是如果不更改学生头文件中的班级私人信息,我怎么能做同样的工作?
  • @afu:你为什么要这么做?
  • @afu - 抱歉,我不明白你的意思?附言我很好奇您如何决定接受哪个答案(:
  • 看看有什么替代方法。实际上,在我将它们保持全局之前,这些字符串是私有的,但是在我改变之后,我看不出我错在哪里。现在可以了。谢谢大家:)
【解决方案2】:

您的 Student.cpp 定义了单个全局指针 Alias 和单个指针 Name。您真正想要的是为每个 Student 对象提供一个单独的 AliasName。您可以通过将 members 添加到类中来做到这一点:

class Student {
public:
  Student(const std::string& a, const std::string& n);
  //...
private:
  std::string Alias;
  std::string Name;
};

Student::Student(const std::string& a, const std::string& n)
  : Alias(a), Name(n)
{}

【讨论】:

    【解决方案3】:

    我可能在这里发疯了,但你不是专门在前面打印,同时向后推吗?

    studentvector.push_back(student);
    cout << studentvector.front() << endl;
    

    你是推到后面,而不是前面,然后打印前面的内容。当然,您不会看到前线变化。您需要向后打印或向前推。如果前推不可用,您可以使用insert(container.begin(), object)

    您还需要将这些全局字符串变量作为成员移动到类中,这样对于Student 的每个实例,学生都有NameAlias 的实例。

    另一个注意事项...您正在动态分配字符串类。字符串类的目的是为您处理char* 字符串的动态内存。据我从您的代码中可以看出,在这种情况下您没有理由使用string*s。 string 将在内部为您处理 newdelete

    【讨论】:

    • 不,studentvector.back();通常会显示向量中的最后一个。问题是学生向量[0] 与即将到来的学生的变化。
    【解决方案4】:

    我同意其他人所说的。但是,我无法重现您所说的问题。特别是,以下(相当恶心的)代码正确输出了两行“Student(foo,bar)”。

    #include <iostream>
    #include <vector>
    #include <string>
    
    // NOTE WELL: many things in this code are bad style and should not be imitated.
    // One of them is the namespace-polluting using-directive below:
    using namespace std;
    
    struct Student {
      string alias, name;
      Student(string a, string n) : alias(a), name(n) {}
    };
    class StudentException : public exception {};
    
    vector<Student*> studentvector;
    
    ostream& operator<<(ostream& stream, Student* student) {
      stream << "Student(" << student->alias << "," << student->name << ")";
      return stream;
    }
    
    void addStudent(const string alias, const string name) throw(StudentException)
    {
      Student* student = new Student(alias, name);
      studentvector.push_back(student);
      cout << studentvector.front() << endl;
    }
    
    int main(void) {
      addStudent("foo","bar");
      addStudent("baz","quux");
    }
    

    了解您的(不工作的)代码与上述代码有何不同可能会有所帮助。

    一些可能相关的评论:

    1. 您不会以某种方式混淆向量的前端和后端吗?
    2. 如果(与您的 addStudent 函数不同)您的实际代码有一个 single Student 对象,并且正在修改它,然后将指向它的指针推送到您的向量上,那么您当然会得到那种你描述的错误结果,因为它每次都是同一个指针。

    【讨论】:

    • 请不要使用using namespace std;,尤其是在为初学者编写示例时。他们会捡起来的!
    • 这就是我所说的“相当恶心”的一部分,看起来好像有问题的特定初学者可能已经在这样做了!但是,为了后代的利益,请注意:在 C++ 中说 using namespace std 几乎总是一件坏事(或者在其他语言中做类似的事情,例如 Python 中的 import * from some_module),你不应该仅仅因为像我这样的懒惰人在玩具示例中这样做就被愚弄了。 -- 现在我要在我的 icky 代码中添加一个注释,说同样的话。
    【解决方案5】:

    std::vector::front() 将返回对向量中第一个元素的引用。 如果你想移除元素,你需要调用 pop_back() ,它将返回元素并从向量中移除。

    【讨论】:

      【解决方案6】:

      如果您有 Boost,请查看Boost Pointer Containers

      【讨论】:

        猜你喜欢
        • 2020-09-15
        • 2016-01-24
        • 1970-01-01
        • 2022-12-17
        • 2021-06-07
        • 2013-02-10
        • 2019-04-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多