c++ - 为什么 gcc 使用我的自定义迭代器优化掉这个 C++11 foreach 循环?

标签 c++ c++11 foreach iterator

我正在尝试编写一些代码来创建序列的函数式样式。我写了一个函数,range(a, b),它返回一个你可以迭代的对象,foreach 风格,遍历数字 a, a + 1, ..., b - 1.然后我写了另一个函数map(f, t),它返回另一个可迭代对象,其中序列中的每个元素都是用相应元素调用f的结果可迭代对象 t.

如果我使用 -O1 或更低版本进行编译,这将按预期工作;使用 -O2 或更高版本时,我的 foreach 循环(在底部的 main 中)得到完全优化并且没有打印任何内容。为什么会这样,我做错了什么?这是我的代码:

template<typename T>
struct _range {
    T a;
    T b;

    _range(T a, T b):
        a(a),
        b(b)
    {
    }

    struct iterator {
        T it;

        iterator(T it):
            it(it)
        {
        }

        bool operator!=(const iterator &other) const
        {
            return it != other.it;
        }

        void operator++()
        {
            ++it;
        }

        T operator*() const
        {
            return it;
        }
    };

    iterator begin() const
    {
        return iterator(a);
    }

    iterator end() const
    {
        return iterator(b);
    }
};

template<typename T>
_range<T> range(const T a, const T b)
{
    return _range<T>(a, b);
}

template<typename F, typename T>
struct _map {
    const F &f;
    const T &t;

    _map(const F &f, const T &t):
        f(f),
        t(t)
    {
    }

    struct iterator {
        const F &f;
        typename T::iterator it;

        iterator(const F &f, typename T::iterator it):
            f(f),
            it(it)
        {
        }

        bool operator!=(const iterator &other) const
        {
            return it != other.it;
        }

        void operator++()
        {
            ++it;
        }

        int operator*() const
        {
            return f(*it);
        }
    };

    iterator begin() const
    {
        return iterator(f, t.begin());
    }

    iterator end() const
    {
        return iterator(f, t.end());
    }
};

template<typename F, typename T>
_map<F, T> map(const F &f, const T &t)
{
    return _map<F, T>(f, t);
}

#include <algorithm>
#include <cstdio>

int main(int argc, char *argv[])
{
    for (int i: map([] (int x) { return 3 * x; }, range(-4, 5)))
        printf("%d\n", i);

    return 0;
}

最佳答案

总结现有评论:

range(-4, 5) 创建一个临时对象,并且(在大多数情况下)临时对象只存在到创建它们的完整表达式的末尾。因此,在您的情况下,返回的 _range 对象在 _map 的构造期间有效,但是一旦 _map 返回>map,完整表达式结束,_range 对象被销毁。

也就是说,因为 _map 保存通过 const ref 而不是通过值传递给其构造函数的参数,这意味着当基于范围的 for 开始执行时, 你的 _map::t 已经是一个悬空引用 – 经典 undefined behavior .

要解决此问题,只需让 _map 按值存储其数据成员即可。

关于c++ - 为什么 gcc 使用我的自定义迭代器优化掉这个 C++11 foreach 循环?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14467324/

相关文章:

c# - 我将如何跳过 foreach 循环中的空格?

c++ pthread 多线程,用于 2 x Intel Xeon X5570,Amazon EC2 HPC ubuntu 实例上的四核 CPU

c++ - 构建跨平台应用程序的最简单方法

c++ - 需要帮助来修复我的代码以执行特定的逻辑

c++11 - 抑制警告:deleting 'void*' is undefined

c++ - 如何防止捕获的 "this"的悬挂指针被 shared_ptr 破坏?

java - Spark toLocalIterator 和迭代器方法之间的区别

c++ - Clang RecursiveASTVisitor 是否有最终访问方法?

c++ - 如何在 Windows HANDLE 中使用 C++ 标准智能指针?

c# - 加快迭代两个 foreach 循环