如何从 C++ 中的“指向对象的指针”向量访问对象

Posted

技术标签:

【中文标题】如何从 C++ 中的“指向对象的指针”向量访问对象【英文标题】:How do I access objects from a vector of "pointer-to-objects" in c++ 【发布时间】:2015-02-15 07:10:34 【问题描述】:

我正在编写一个程序来创建一个指向对象的向量。

如何访问指针从指向对象向量中引用的各个对象?

我正在尝试为向量引用中的指针所指向的每个对象调用 Object 类中的 speak() 函数。

感谢您的宝贵时间

class Object

public:
    void speak()
    
        cout<<"Hello!"<<endl;
    
;

int main()

    int choice;

    vector<Obj*> objVector; //create empty vector of "pointer-to-object"
    Object* ptrObj; //point to object

    while (choice!=5)
    
        cout <<"1.Create Object\n";
        cout <<"2.Destroy Object\n";
        cout <<"3.Print number of existing Objects\n";
        cout <<"4.Tell existing Objects to say Hello\n";
        cout <<"5.Quit Program"<<endl;
        cout <<"Please enter your choice: ";
        cin >> choice;

    if (choice==5)
        cout <<"\nProgram is quitting\n"<<endl;
    else if (choice==1)
    
        ptrObj= new Object;
        ObjVector.push_back(ptrObj); //adding an Object object
    
    else if (choice==2)  //remove object
    
        objVector.pop_back();
    
    else if (choice==3)
    
        cout <<"\nThere are " << objVector.size() <<" objects total.\n" << endl;
    
    else if (choice==4)
    
        for (int i=0; i<objVector.size(); i++)
        
           ????????????
        
    
    
    return 0;

【问题讨论】:

与您的问题无关,我注意到您的程序正在泄漏内存:无论何时使用new,您也应该使用delete。当你从向量中删除一个对象时,你只是扔掉了指针,但对象仍在内存中,占用空间。 pop_back() 返回它正在删除的指针,您应该将该指针存储在某处或 delete 它,也许像:ptrObj=objVector.pop_back(); delete ptrObj; @greyfade 确实如此。或者使用unique_ptr的向量 【参考方案1】:

在您现有的代码中,您可以完全按照在代码中其他地方使用指针的方式访问指针:

Object* obj = objVector[i];
obj->speak();
// or, simply:
objVector[i]->speak();

使用运算符-&gt; 只是表示(*objVector[i]).speak() 的另一种方式。

另外,编写循环的惯用方法如下所示:

for(vector<Object*>::iterator it = objVector.begin(); it != objVector.end(); ++it) 
    // iterators work like another level of pointers, and need to be dereferenced:
    (*it)->speak();

如果你的编译器支持 C++11,你可以这样重写循环:

for(auto it = std::begin(objVector); it != std::end(objVector); ++it) 
    (*it)->speak();

或者像这样,使用基于范围的 for,它为您取消引用迭代器:

for(auto& obj : objVector) 
    obj->speak();


顺便说一句,在某些情况下,您根本无法确定 objVector[i] 是否在向量中,访问它可能会使您的程序崩溃,甚至导致恶魔从您的鼻腔飞出。

为了增加安全性,您可以使用 at 函数引用向量中的位置,如下所示:

try 
    for (int i=0; i<objVector.size(); i++)
    
        Object* obj = objVector.at(i);
        obj->speak();
    
 catch (const std::out_of_range& ex) 
    cerr << "no object at position " << i << " in objVector" << endl;
    cerr << "objVector says " << ex.what() << endl;

但请注意,这要慢得多,尽管它让您有机会处理 catch 块中的问题。如果at 函数抛出异常——out_of_range 类型的异常,try 块将运行循环并停止并运行catch 块。另请注意,使用[i] 不会做同样的事情,因为它不会引发异常 - 它甚至不会检查i 是否在向量的长度内。这恰好也是[i].at(i) 快的原因。

最后,还要注意使用迭代器的循环不能遇到这个特殊问题,只要您在从向量中添加或删除某些内容后不要尝试使用迭代器。

【讨论】:

您对使用at() 方法有何看法。我认为它比[ ] 运算符更安全,但可能会更慢【参考方案2】:

最简单的方法是使用*(objVector[i])

要访问发言,objVector[i]-&gt;speak 只是更短。

【讨论】:

【参考方案3】:

您可以使用 * 取消引用它们。像 *(ObjVector[i]) 但是,如果您只需要调用对象的方法,则可以使用 -> ObjVector[i]-&gt;speak()

【讨论】:

【参考方案4】:

与问题无关,但我删除了一些评论以修改程序。

正如其他人指出的那样,您可以通过执行objVector[i]-&gt;speak() 从向量中包含的指针调用对象函数。

但是,正如@greyfade 指出的那样,存在内存泄漏问题。当new 创建对象时,您必须删除对象。你可以像这样通过delete删除对象,

Object* ptr = objVector.back();
objVector.pop_back();
delete ptr;

要消除内存泄漏问题,您可以将Object 对象直接存储在objVector 中,而不是Object*。这样,您就不必担心删除对象。你可以这样做,

int main()

    int choice;

    vector<Object> objVector; //create empty vector of "pointer-to-object"

    while (choice!=5)
    
        cout <<"1.Create Object\n";
        cout <<"2.Destroy Object\n";
        cout <<"3.Print number of existing Objects\n";
        cout <<"4.Tell existing Objects to say Hello\n";
        cout <<"5.Quit Program"<<endl;
        cout <<"Please enter your choice: ";
        cin >> choice;

    if (choice==5)
        cout <<"\nProgram is quitting\n"<<endl;
    else if (choice==1)
    
        objVector.emplace_back(); //adding an Object object
    
    else if (choice==2)  //remove object
    
        objVector.pop_back();
    
    else if (choice==3)
    
        cout <<"\nThere are " << objVector.size() <<" objects total.\n" << endl;
    
    else if (choice==4)
    
        for (auto& obj : objVector)
        
          obj.speak();
        
    
    
    return 0;

此代码使用 c++11 功能。您可以通过调用emplace_back 添加对象并通过调用pop_back() 删除对象。这不甜吗?

还有一件事。您忘记了标题上的一些代码。没有这些头文件就无法编译这段代码,

#include <iostream>
#include <vector>
using namespace std;

如果这段代码对你有帮助,我会很高兴。

【讨论】:

以上是关于如何从 C++ 中的“指向对象的指针”向量访问对象的主要内容,如果未能解决你的问题,请参考以下文章

从 2D 向量创建 1D 向量的函数(错误:表达式必须具有指向对象的指针类型)

C ++在向量迭代中删除并返回指向对象的指针

无法从文件复制到指向对象的指针向量

在删除指向动态分配对象的指针向量中的元素之前,我需要做啥?

我是否正确删除了指向对象的向量?

我是不是正确删除了指向对象的指针向量?