如何使用自定义迭代器循环通过智能指针指向类

Posted

技术标签:

【中文标题】如何使用自定义迭代器循环通过智能指针指向类【英文标题】:How to cycle through smart pointer to a class with custom iterator 【发布时间】:2021-10-29 14:43:20 【问题描述】:

我有一个指向带有自定义迭代器的类的智能指针。我需要遍历它,但找不到任何示例。

struct SomeContrainer

   int a;


struct ListClass

   std::vector<SomeContrainer>::iterator begin()  return m_devs.begin(); 
   std::vector<SomeContrainer>::iterator end()    return m_devs.end();                                            

   void add( const SomeContrainer& dev )  m_devs.push_back( dev ); 

   private:
      std::vector<SomeContrainer> m_devs;
;

typedef std::unique_ptr<ListClass> ListPtr_t;


void Foo_Add( const ListPtr_t& list )

   SomeContrainer dev1, dev2;
   dev1.a = 10;
   dev2.a = 100;
   list->add(dev1);
   list->add(dev2);


void DoSomeWorkOtherList( const ListPtr_t& list )

   for( auto const& dev : list )    // <-- how to iterate over list ???
   


// -----------

ListPtr_t pMyList( new ListClass() );

Foo_Add( pMyList );
DoSomeWorkOtherList(pMyList );

如果我不使用智能指针并且只有一个对象 ListClass list 我正在使用 C++11 并且无法升级,那么它工作正常。

【问题讨论】:

由于没有所有权转让,你的方法应该直接取ListClass:void Foo_Add(ListClass&amp; list) 【参考方案1】:

你需要取消引用它

void DoSomeWorkOtherList( const ListPtr_t& list ) // void(const unique_ptr<ListClass>&)

   for( auto const & dev : *list ) // <-- how to iterate other list ???
   


对于有问题的代码不是必需的,但您可能还想提供 beginend 的 const 版本。

std::vector<SomeContrainer>::const_iterator begin() const  return m_devs.begin(); 
std::vector<SomeContrainer>::const_iterator end() const  return m_devs.end();                                            

【讨论】:

【参考方案2】:

您有不同的选择,仅举几例:

    将 const 引用传递给列表。
void DoSomeWorkOtherList(const ListClass& list)

   std::cout << "v1 (const ListClass&): ";
   for (const auto& dev : list)  std::cout << dev.a << " "; 
   std::cout << "\n";

    将 const 原始指针传递给列表。
void DoSomeWorkOtherList(const ListClass* list)

   std::cout << "v2 (const ListClass*): ";
   if (list)
   
      for (const auto& dev : *list)  std::cout << dev.a << " "; 
   
   std::cout << "\n";

    将 const 引用传递给指向列表的唯一指针。
void DoSomeWorkOtherList(const ListPtr_t& list)

   std::cout << "v3 (const ListPtr_t&): ";
   if (list)
   
      for (const auto& dev : *list)  std::cout << dev.a << " "; 
   
   std::cout << "\n";

为了确定最适合您的选项,参考 C++ 核心指南会很有帮助。 如果函数代码不暗示所有权更改,一般建议使用指针或引用

F.7: For general use, take T* or T& arguments rather than smart pointers F.60: Prefer T* over T& when “no argument” is a valid option

上述情况的可能调用者代码是:

int main()

    ListPtr_t uplstd::make_unique<ListClass>();
    upl->add(7);
    upl->add(8);
    DoSomeWorkOtherList(*upl);
    upl->add(9);
    DoSomeWorkOtherList(upl.get());
    Foo_Add(*upl);
    DoSomeWorkOtherList(upl);


// Outputs:
//     v1 (const ListClass&): 7, 8
//     v2 (const ListClass*): 7, 8, 9
//     v3 (const ListPtr_t&): 7, 8, 9, 10, 100

Demo

【讨论】:

以上是关于如何使用自定义迭代器循环通过智能指针指向类的主要内容,如果未能解决你的问题,请参考以下文章

如何使用智能指针跟踪类的对象?

智能指针的迭代和容器

如何防止智能指针循环引用问题

C++智能指针及循环引用

C++智能指针及循环引用

获取双指针指向的对象