C++中的结构体向量

3

我在创建结构体向量时遇到了问题。在我的AddApp函数中,我无法将新分配的结构推入向量中。我收到了“无效参数”的错误消息。我查看了一些类似问题的解决方法,但没有什么可以帮助到我。有谁能指出我的逻辑漏洞在哪里吗?谢谢。

class AppHolder
{
private:
    struct Info
    {
    int refNumber;
    string name;
    string link;
    };

vector<Info> dataBase;

public:
    void AddApp(int ,string ,string );
};

void AppHolder::AddApp(int R, string N, string L)
{
Info *newApp = new Info;
newApp -> name = N;
newApp -> link = L;
newApp -> refNumber = R;

dataBase.push_back(newApp);
}

2
你知道 TypeType* 有什么不同吗? - Aleksei Zabrodskii
2
你试图推回一个指针,但向量模板化为你的结构体的实例。 - ypnos
4个回答

8
您的代码失败的原因是std::vector<Info>::push_back要求您传递类型为Info的对象,但您传递了Info*

我们可以通过直接使用Info对象而不是使用指向new变量的指针来解决此问题:

void AppHolder::AddApp(int R, string N, string L)
{
    Info newApp;
    newApp.name = N;
    newApp.link = L;
    newApp.refNumber = R;
    dataBase.push_back(newApp);
}

Info* newApp = new Info; 声明了一个指向 Info 对象的指针,并将其初始化为动态创建的类型为 Info 的对象的地址。必须在后面删除它,否则析构函数不会被调用,内存也不会被释放。

Info newApp; 声明了一个自动变量,类型为 Info,其析构函数在作用域结束时被调用,并且内存将被释放。

在现代 C++ 中,使用指针的 new 不被鼓励,因为它需要手动删除指针,这是不安全的(如果在删除之前抛出异常,则资源不会被删除),并且涉及编写大量代码(复制构造函数、复制赋值运算符、析构函数、移动构造函数和移动赋值运算符)以确保类能够正确工作。但是,在某些情况下需要使用指针(在容器中存储派生类的实例),在这种情况下,您可以使用智能指针来管理资源。


2

The declaration

vector<Info> dataBase;

声明一个向量,其中包含Info对象。在初始化程序中,

Info *newApp = new Info;
newApp -> name = N;
newApp -> link = L;
newApp -> refNumber = R;

dataBase.push_back(newApp);

语句 dataBase.push_back(newApp); 尝试将一个指向Info 结构的指针推入向量中(但是您的向量需要对象,而不是对象的指针)。
因此,您可以声明一个指向Info结构的指针向量-vector<Info *> - 并记住在类析构函数中释放每个指针。或者,只需在堆栈上创建一个Info结构(即实际对象),并将其推入向量中(这将在向量内部创建结构的副本-将使用默认结构复制构造函数,在您的情况下是可以的,因为该结构不包含指针等任何需要或不支持深层复制的内容)。
后一种方法更安全,因为您不必记住释放任何内容,并且在这种情况下可能更有效率,因为虽然您正在复制结构,但不会对操作系统进行昂贵的内存分配调用。

2
你的编译器报错是因为你定义了dataBase作为一个Info实例的向量,而你正在尝试推入指向Info实例的指针。
将vector声明更改为vector是一种方法,或者更改AddApp方法:
void AppHolder::AddApp(int R, string N, string L)
{
    Info newApp;
    newApp.name = N;
    newApp.link = L;
    newApp.refNumber = R;

    dataBase.push_back(newApp);
}

正如其他人所指出的那样,在C++中使用new是不被鼓励的,因此最好保留您的容器定义。更改您的实现以使用正确的类型。

一位评论者澄清了为什么在C++中使用new时应该小心。


2
并不是说使用 new 不被鼓励(毕竟它有存在的理由),而是手动分配内存应该小心谨慎,以防止内存泄漏(以及其他难以发现/修复的与内存相关的错误)。 通常,在这种情况下,确保内存正确清理的好方法是使用 unique_ptr(或其他智能指针包装模板)而不是原始指针。 话虽如此,我更喜欢这个特定问题的非堆解答,而不是不必要的内存分配版本。 - Zac Howland

0

你必须将此转换为:

vector<Info> dataBase;

转换成这个:

vector<Info*> dataBase;

由于您想要将指针 push_back 到 vector 中,而 vector 被声明为接受对象,因此需要进行转换。


-1: 将原始指针存储在容器中总是会失败的(这需要编写代码来满足三五法则,以及不安全的异常代码)。总有比手动操作更好的替代方案。 - milleniumbug

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接