我用它的自定义迭代器编写了一个自定义容器。由于容器的特定特性,必须对迭代器进行惰性评估。为了这个问题,代码的相关部分是迭代器的解引用运算符,它以这种方式实现
template<typename T>
struct Container
{
vector<T> m_Inner;
// This should calculate the appropriate value.
// In this example is taken from a vec but in
//the real use-case is calculated on request
T Value(int N)
{ m_Inner.at(N); }
}
template<typename T>
struct Lazy_Iterator
{
mutable pair<int, T> m_Current;
int Index
Container<T>* C
Lazy_Iterator(const Container& Cont, int N):
m_Current{Index, T{}}, Index{N}, C{&Cont}
{ }
pair<int, T>&
operator*() const // __attribute__((noinline)) (this cures the symptom)
{
m_Current.first = Index; /// Optimized out
m_Current.second = C->Value(Index); /// Optimized out
return m_Current;
}
}
因为迭代器本身就是一个模板,它的函数可以被编译器自由地内联。
当我在没有优化的情况下编译代码时,返回的值会按预期更新。在某些情况下,当我使用发布编译器优化(GCC 4.9 中的 -O2)时,即使 m_Current 成员被标记为可变,编译器也会优化我标记为已优化的行。因此,返回值与迭代器应该指向的值不匹配。
这是预期的行为吗?您是否知道任何可移植的方式来指定应该评估该函数的内容,即使它被标记为 const?
我希望这个问题足够详尽以至于有用。如果在这种情况下更多细节可能会有所帮助,请提出建议。
编辑:
要回答一个评论,这是从一个小型测试程序中获取的潜在用法:
Container<double> myC;
Lazy_Iterator<double> It{myC, 0}
cout << "Creation: " << it->first << " , " << it->second << endl;
auto it2 = it;
cout << "Copy: "<< it2->first << " , " << it2->second << endl;
cout << "Pre-increment: " << (it++)->first << " , " << it->second << endl;
cout << "Post-increment: " << (++it)->first << " , " << it->second << endl;
cout << "Pre-decrement: " << (it--)->first << " , " << it->second << endl;
cout << "Post-decrement: " << (--it)->first << " , " << it->second << endl;
cout << "Iterator addition: " << (it+2)->first << " , " << (it+2)->second << endl;
cout << "Iterator subtraction: "<< (it-2)->first << " , " << (it-2)->second << endl;
reverse_iterator<Lazy_Iterator> rit{it};
cout << "Reverse Iterator: " << rit->first << " , " << rit->second << endl;
auto rit2 = rit;
cout << "Reverse Iterator copy: " << rit2->first << " , " << rit2->second << endl;
cout << "Rev Pre-increment: " << (rit++)->first << " , " << rit->second << endl;
cout << "Rev Post-increment: " << (++rit)->first << " , " << rit->second << endl;
cout << "Rev Pre-decrement: " << (rit--)->first << " , " << rit->second << endl;
cout << "Rev Post-decrement: " << (--rit)->first << " , " << rit->second << endl;
cout << "Rev Iterator addition: " << (rit+2)->first << " , " << (rit+2)->second << endl;
cout << "Rev Iterator subtraction: "<< (rit-2)->first << " , " << (rit-2)->second << endl;
除最后两行外,所有测试的测试结果都符合预期
当优化开启时,测试的最后两行会崩溃。
该系统实际上运行良好,并不比任何其他迭代器更危险。当然,如果容器在他的眼皮底下被删除,它会失败,并且通过复制使用返回的值可能更安全,而不仅仅是保留引用,但这是题外话