【问题标题】:Is it possible to create a vector of pointers?是否可以创建指针向量?
【发布时间】:2010-10-23 11:14:09
【问题描述】:

只是想知道,由于我遇到的一个问题,是否可以创建一个指针向量?如果是这样,怎么办?特别是关于使用迭代器和 .begin() ,即:如何将此向量转换为指针向量:

class c
{
     void virtual func();
};

class sc:public c
{
     void func(){cout<<"using func";}
};

sc cobj;

vector<c>cvect
cvect.push_back(cobj);
vector<c>::iterator citer

for(citer=cvect.begin();citer<cvect.end();citer++)
{
     citer->func();
}

【问题讨论】:

    标签: c++ stl pointers vector pure-virtual


    【解决方案1】:

    当然。

    vector<c*> cvect;
    cvect.push_back(new sc);
    vector<c*>::iterator citer;
    for(citer=cvect.begin(); citer != cvect.end(); citer++) {
      (*citer)->func();
    }
    

    注意事项:

    如果您像我在示例中所做的那样使用动态分配的内存,则需要自行清理

    例如:

     for(...) { delete *i; }
    

    这可以通过使用shared_ptrs 的向量来简化(如boost::shared_ptr)。不要尝试为此使用std::auto_ptr,它不起作用(甚至无法编译)。

    要记住的另一件事是,您应该尽可能避免使用&lt; 来比较循环中的迭代器,它只适用于模拟随机访问迭代器的迭代器,这意味着您不能将代码更改为使用例如std::list

    【讨论】:

      【解决方案2】:

      vector &lt;c&gt; cvect 不是指针向量。它是类型 c 的对象的向量。你想要vector &lt;c*&gt; cvect。和你可能想要的:

      cvect.push_back( new c );
      

      然后,给定一个迭代器,你想要这样的东西:

      (*it)->func();
      

      当然,你很可能一开始就不想要指针向量...

      【讨论】:

      • func() 是一个虚函数,所以我猜这里需要指针向量。
      • 如果 push_back() 抛出,你可能想避免泄露新的 c。
      【解决方案3】:

      是的,这是可能的,事实上,如果您希望向量包含来自整个类层次结构而不是单一类型的对象,则使用指针是必要的。 (不使用指针会导致object slicing 的可怕问题——所有对象都会默默地转换为基类类型。编译器不会诊断出这种情况,而且几乎肯定不是你想要的。)

      class c
      {
           void virtual func();
      };
      
      class sc:public c
      {
           void func(){cout<<"using func";}
      };
      
      sc cobj;
      
      vector<c*> cvect;             // Note the type is "c*"
      cvect.push_back(&cobj);       // Note the "&"
      vector<c*>::iterator citer;
      
      for(citer=cvect.begin();citer != cvect.end();citer++)   // Use "!=" not "<"
      {
           (*citer)->func();
      }
      

      请注意,对于指针向量,您需要自己进行内存管理,所以要非常小心——如果您将使用本地对象(如上所述),它们一定不能脱落容器之前的范围。如果您使用指向使用new 创建的对象的指针,则需要在销毁容器之前手动delete 它们。在这种情况下,您绝对应该考虑使用智能指针,例如 Boost 提供的 smart_ptr

      【讨论】:

        【解决方案4】:

        是的,当然。

        // TestCPP.cpp : Defines the entry point for the console application.
        //
        
        #include "stdafx.h"
        #include <iostream>
        #include <vector>
        
        
        using namespace std;
        
        class c
        {
        public:
            void virtual func() = 0;
        };
        
        class sc:public c
        {
        public:
            void func(){cout<<"using func";}
        };
        
        int _tmain(int argc, _TCHAR* argv[])
        {
            sc cobj;
        
            vector<c*> cvect;
            cvect.push_back(&cobj);
            vector<c*>::iterator citer;
        
            for(citer=cvect.begin();citer<cvect.end();citer++)
            {
                (*citer)->func();
            }
        
            return 0;
        }
        

        请注意vector&lt;c*&gt; cvect的声明和cvect.push_back(&amp;cobj)的使用。

        根据提供的代码,您以错误的方式使用迭代器。要访问迭代器指向的成员,您必须使用 *citer 而不是单独使用 citer

        【讨论】:

          【解决方案5】:

          您已经为指针向量创建了vector&lt;c*&gt;。然后使用new 为c 对象分配内存并将它们压入vector。另外,不要忘记您必须自己 delete 并且 vector.clear() 不会释放为 c 对象分配的内存。此处必须将 c 存储为指针向量,否则对虚函数的调用将不起作用。

          【讨论】:

            【解决方案6】:

            试试Boost Pointer Container Library。与常规的指针向量相比,它有几个优点,例如:

            my_container.push_back( 0 );            // throws bad_ptr 
            ptr_vector<X> pvec; 
            std::vector<X*> vec;
            ( *vec.begin() )->foo(); // call X::foo(), a bit clumsy
            pvec.begin()->foo();     // no indirection needed
            

            【讨论】:

              猜你喜欢
              • 2020-01-18
              • 1970-01-01
              • 1970-01-01
              • 2012-06-13
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多