【问题标题】:Iterating through array of object pointers in C++ the old way (without range-based for)?以旧方式迭代 C++ 中的对象指针数组(没有基于范围的 for)?
【发布时间】:2015-01-08 23:20:49
【问题描述】:

我不是很精通C++,但是我来了以下代码:

BaseManager* allManagers[] =
{
    mColorManager,
    mToolManager,
    mLayerManager,
    mPlaybackManager,
    mViewManager
};

for ( BaseManager* pManager : allManagers )
{
    pManager->setEditor( this );
    pManager->init();
}

我使用older g++,所以我不能使用-std=c++11,我必须使用-std=c++0x。看看error: expected initializer before ‘:’ token 中的“老派”等价物,我希望以下方法能奏效:

for ( auto it = allManagers.begin(); it != allManagers.end(); ++it )
{
    BaseManager* pManager = *it;
    pManager->setEditor( this );
    pManager->init();
}

...但它失败了:

error: request for member ‘begin’ in ‘allManagers’, which is of non-class type ‘BaseManager* [5]’
error: unable to deduce ‘auto’ from ‘<expression error>’

所以我收集了,因为这个 allManagers 显然只是一个 C 数组,它不是一个带有方法的对象(如 .begin) - 所以最后,我终于得到了那个片段来编译:

for ( int i=0 ; i<5 ; i++ )
{
    BaseManager* pManager = allManagers[i];
    pManager->setEditor( this );
    pManager->init();
}

... 但是,这需要我手动写入数组长度,我不喜欢这样。

所以,我的问题是:在不使用基于范围的 for 循环的情况下,迭代这样一个指针数组的正确方法是什么——而且不必显式输入硬编码的数组长度?

【问题讨论】:

  • 下面的迭代器版本更好,但是:for ( int i = 0; i &lt; (sizeof(allManagers) / sizeof(allManagers[0])); ++i ) 是一种 C-ish 方式。

标签: c++ arrays


【解决方案1】:

你可以使用:

for ( auto it = std::begin(allManagers); it != std::end(allManagers); ++it )
{

不过,这些也是 C++11 的特性。一些 C++11 之前的编译器可能支持它们,但不能保证。

没有可使用的 C++11 编译器,您可以使用:

size_t numObjects = sizeof(allManagers)/sizeof(allManagers[0]);
for ( size_t i = 0; i < numObjects; ++i  )
{
   BaseManager* manager = allManagers[i];

【讨论】:

  • 很好,完全没有意识到这是在标准库中。对于 OP,如果您好奇,也可以在这里查看如何实现它们:stackoverflow.com/questions/5897319/…
  • 谢谢@RSahu - 我真的很期待这个,但显然我的编译器太旧了,因为我得到了 "error: 'begin' is not a member of 'std'" 。 ..
【解决方案2】:

要么跟踪变量中的数组长度,要么使用 std::array 或 std::vector。

编辑:如果你想创建自己的 ArrayLen() 方法,你可以这样做:

template<class T, size_t Size>
static inline size_t ArrayLen(const T(&arr)[Size])
{
    return Size;
}

那么你可以这样做:

for(size_t i = 0; i < ArrayLen(allManagers); ++i)
{
    BaseManager * pManager = allManagers[i];

【讨论】:

  • 谢谢@mbgda——这是否意味着“旧”c++ 中没有函数来确定“普通”C 数组的长度(如伪代码int mylen = len(allManagers);)?跨度>
  • @sdaau 您可以使用我在别处链接的页面中的修改代码获取数组的长度,如下所示:template&lt;class T, size_t Size&gt; size_t ArraySize(const T(&amp;array)[Size]) { return Size; }
【解决方案3】:

allManagers 不是容器。它是一个指针数组,因此不能使用.begin()

如果您想确定数组的大小,只需执行以下操作:

int n = sizeof(allManagers)/sizeof(allManagers[0]);

查看this 问题了解更多信息。请注意,您的数组在堆栈中。

【讨论】:

  • 感谢您的确认,@G.Samaras
  • 欢迎您@sdaau。看看我的编辑。顺便说一句,问题很好。
  • 再次感谢@G.Samaras - 编辑正是我所需要的;我尝试了计数循环for ( int i=0 ; i&lt; (sizeof allManagers / sizeof allManagers[0]) ; i++ ),它编译得很好!所以我接受了这个答案(即使我希望我可以使用@RSahu 指出的语法)。干杯!
  • 不客气。编译器可能会为您执行此操作(使用所需的优化标志),但是您最好将除法的结果“缓存”到变量中(就像我的回答一样)并将其置于 for 的控制之下。否则每次执行for检查都会执行! @sdaau
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-19
  • 2021-11-17
  • 2015-09-30
  • 2021-05-22
  • 2011-08-08
  • 1970-01-01
相关资源
最近更新 更多