【问题标题】:C++ - Adding objects to an std::vector, instantiated in a loopC++ - 将对象添加到 std::vector,在循环中实例化
【发布时间】:2023-03-15 23:39:01
【问题描述】:

我是一名专家级 Java 程序员,正在尝试将我的知识移植到 C++ 中。这不是家庭作业,只是我正在尝试学习的 C++ 等价概念。

我想要做的是使用循环“生成”自定义类型的对象列表。这就是我在 Java 中的做法:

public class TestClass
{
   private ArrayList<ExampleClass> _exampleObjects;
   private int _numObjects = 10;

   public void populateList()
   {
      _exampleObjects = new ArrayList<ExampleClass>();

      for(int i = 0; i < _numObjects; i++)
      {
         _exampleObjects.add(new ExampleClass());
      }
   }

   public void doStuffWithListItems()
   {
      for(ExampleClass e : _exampleObjects)
      {
         e.performAction();
      }
   }
}

超级简单的东西。创建一个列表,遍历任意循环并向其中添加对象。然后,遍历这些对象并将它们用于任何目的。

TestClass.h:

class TestClass
{
   public:
      // Constructor, copy constructor, destructor definitions

      void populateList();
      void doStuffWithListItems(); 
   private:
      std::vector<ExampleClass> _exampleObjects;
      const int _numObjects = 10;
};

TestClass.cpp:

void TestClass::populateList()
{
   for(int i = 0; i < _numObjects; i++)
   {
      ExampleObject obj;
      _exampleObjects.push_back(obj); 

      /* What actually goes here in place of obj? */
   }
}

void TestClass::doStuffWithListItems()
{
   for(auto it = _exampleObjects.begin(); it != _exampleObjects.end(); it++)
   {
      /* What do i do with my iterator to access my object? */
   }
}

我的理解是,我在第一个循环中初始化我的对象时,它们会超出范围并在每次循环迭代结束时死亡。是对的吗?如果是这样,我如何创建一个持久实例?

我尝试了 shared_ptr from 并且显然能够持久存储它们,但我终其一生都无法弄清楚如何从 shared_ptr 的迭代器中取消引用。

我觉得这应该是一个非常简单的概念。我只是似乎无法解决。我已经阅读了很多关于 C++ 范围和循环的内容。我似乎在两者上都找不到任何东西。

【问题讨论】:

    标签: c++ collections scope instantiation


    【解决方案1】:
    ExampleObject obj;
    _exampleObjects.push_back(obj); 
    
    /* What actually goes here in place of obj? */
    

    什么都没有。你所拥有的是正确的,假设ExampleClass 有一个工作副本构造函数。如果您的编译器支持 C++11(并且由于您使用的是 auto,它至少部分支持),您可以为自己保存一份副本。

    _exampleObjects.emplace_back();
    

    这会在向量中的适当位置构造一个对象,将参数(在本例中为无)转发给匹配的构造函数(在本例中为默认 ctor)。要从迭代器访问对象,请执行以下操作:

    for(auto it = _exampleObjects.begin(); it != _exampleObjects.end(); it++)
    {
       it->performAction();
    }
    

    同样,C++11 可以让事情变得更好。

    for(auto & obj : _exampleObjects)
    {
        obj.performAction();
    }
    

    我的理解是我首先在哪里初始化我的对象 循环,它们会超出范围并在每次循环迭代结束时死亡。

    正确。

    如果是这样,我如何创建一个持久实例?

    vector&lt;&gt;::push_back 负责这个。它将参数复制到向量中。换句话说,它不是在循环中创建的同一个对象,它是一个副本。您只需要确保ExampleClass 具有完整的复制语义。

    我这辈子都想不出如何取消引用 shared_ptr

    的迭代器

    如果您有一个指向共享指针向量的迭代器(称为it),您将取消引用它,并调用存储对象的成员函数,如下所示:

    (*it)->performAction();
    // alternatively
    (**it).performAction();
    

    【讨论】:

    • 谢谢。这是一个理想的答案。 :D
    • @ScottDrew:我添加了一些额外的信息来澄清你在代码之后提出的问题,以防你仍然想知道。
    • 谢谢,额外的信息确实有帮助。我觉得我现在已经真正开始掌握 C++,可以在实际项目中实际使用它了。非常感谢您的快速回答。
    【解决方案2】:

    理想的答案提出了一个非常糟糕的主意 - 在循环中的迭代器上使用后增量 ++。 你永远不应该在只需要迭代的循环中使用它,因为后增量必须返回迭代器在递增之前的值;所以,之前的值需要被复制到某个地方。 从性能的角度来看,这并不好,而且是一个糟糕的代码风格标志。

    【讨论】:

    • 你说得很好。不过,我并不是真的建议后增量,我只是在复制 OP 的循环,因为这不是问题所在。
    猜你喜欢
    • 2023-03-04
    • 2016-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-24
    • 2022-01-03
    相关资源
    最近更新 更多