C++11:使用 foreach 循环遍历智能指针

问题:

在 C++11 中,你想使用新的 for 循环语法遍历智能指针(auto_ptrshared_ptr 等)集合,比如 std::vector

让我们试试:

example.cpp
using namespace std;
shared_ptr<vector<int> > smartptr(/* A ptr to your vector */);
for(int s : smartptr) {
    /* 做一些有用的事情 */
}

尝试编译此代码时,GCC 发出以下错误消息(为简单起见省略其他行)

errors.txt
error: no matching function for call to 'begin(std::shared_ptr<std::vector<int> >&)'
error: no matching function for call to 'end(std::shared_ptr<std::vector<int> >&)'

或者,当设置 LANG=de 时:

errors-de.txt
Fehler: keine passende Funktion für Aufruf von »begin(std::shared_ptr<std::vector<int> >&)«
Fehler: keine passende Funktion für Aufruf von »end(std::shared_ptr<std::vector<int> >&)«

解决方案 1(推荐):

只需解引用指针(这有效因为 operator* 在智能指针上定义):

solution1.cpp
using namespace std;
shared_ptr<vector<int> > smartptr(/* A ptr to your vector */);
for(int s : *smartptr) {
    /* 做一些有用的事情 */
}

解决方案 2:

在你的源代码中 for 循环之前包含以下代码:

shared_ptr_begin_end.hpp
#include <memory>
template<typename T>
auto inline begin(std::shared_ptr<T> ptr) -> typename T::iterator {
    return ptr->begin();
}

template<typename T>
auto inline end(std::shared_ptr<T> ptr) -> typename T::iterator {
    return ptr->end();
}

上面的源代码仅适用于共享指针,但你可以简单地将 std::shared_ptr 替换为 std::auto_ptrstd::weak_ptr 或你喜欢的任何类型,假设它可以使用 * 解引用。

此解决方案使你免于解引用指针,这可能是好是坏取决于你偏好的编码风格。根据你的编译器设置,额外的符号可能会或可能不会被优化掉(inline 关键字只是建议,对编译器不是强制性的),但在大多数情况下,你最终可能得到与使用解决方案 1 完全相同的速度。

为什么这有效?

上面的源代码仅适用于共享指针,但你可以简单地将 std::shared_ptr 替换为 std::auto_ptr、std::weak_ptr 或你喜欢的任何类型,假设它可以使用 * 解引用。

此解决方案使你免于解引用指针,这可能是好是坏取决于你偏好的编码风格。根据你的编译器设置,额外的符号可能会或可能不会被优化掉(inline 关键字只是建议,对编译器不是强制性的),但在大多数情况下,你最终可能得到与使用解决方案 1 完全相同的速度。

解决方案 3

如果你使用 boost::foreach,这可能对你有效,但如果编译器不优化它,解决方案相当慢。

它基于 boost::foreach 可以接受一对迭代器的事实。

boost_foreach_example.cpp
BOOST_FOREACH(string str, foreach_wrap_ptr(mySharedPtr)) {
    //...
}

Check out similar posts by category: C/C++