状态函子STL:未定义的行为 [英] Stateful functors & STL : Undefined behaviour

查看:140
本文介绍了状态函子STL:未定义的行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遵循此函数对象教程 a>

以下复制粘贴:

我无法理解以下内容:

谓词应始终被实现为无状态函数对象,以避免意外的结果。不能保证算法在内部复制谓词的频率。因此,具有作为有状态函数对象实现的谓词可能具有未经处理的结果。

Predicates should always be implemented as stateless function objects to avoid unexpected results. There is no guarantee how often an algorithm might internally copy the predicate. Thus, having predicates that are implemented as stateful function objects might have unexecpted results.

示例如下:

#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>

class predicate
{
public:
   predicate(int condition) :
      condition_(condition), state_(0) {}
   bool operator()(int) { return ++state_ == condition_; }

private:
   int condition_;
   int state_;
};

int main()
{
   std::vector<int> vec;
   vec.push_back(1);
   vec.push_back(2);
   vec.push_back(3);
   vec.push_back(4);
   vec.push_back(5);

   predicate p(2);
   std::vector<int>::iterator pos =
      std::remove_if(vec.begin(), vec.end(), p);
   vec.erase(pos, v.end());

   std::copy(vec.begin(), vec.end(),
             std::ostream_iterator<int>(std::cout, " "));

   return 0;
}



如果我正确理解(读取)它正试图删除元素在向量中标记为2。 remove_if算法返回容器的新端并尝试清除所有容器。

If I understand (read) it correctly , it is attempting to remove the element marked as 2 in the vector. remove_if algorithm returns a new end of the container and attempting to erase all of it.

输出:

1 3 5

*很明显,不仅第二个元素删除,但第四个。这个好奇心的答案就是使用的算法remove_if在执行期间内部复制谓词。这个内部副本创建一个包含其原始状态的新谓词对象。

*Clearly, not only the second element has been removed but also the fourth one. The answer to this curiosity is simply that the used algorithm 'remove_if' internally copies the predicate during its execution. And this internal copy creates a new predicate object containing its original state.*

虽然我可以看到发生了什么,场景,甚至实际上标记了第4个元素被移动到容器的结尾。这是与单通或多通的算法有关吗? (如果有人可以指出我正确的方向如何推论的话,我也会感激的)。

Though I can read what seems to be happening, I am unable to picture what is happening behind the scenes which actually marked even the 4th element to be moved to the end of the container. Does this have to do with an algorithm being single pass or multiple pass? ( also I would be grateful if some one could point me in the right direction how to deduce the same)

在旁注中,如果我评论擦除&请注意输出。

On a side note , if i comment the erase & note the output.

1 3 5 4 5

导致容器损坏的原因是什么?

What causes the container to get corrupted ?

推荐答案

应以面值计算。对于大多数STL算法,您不应实现您的谓词函子,使其具有可观察状态(AKA副作用),因为:

The meaning of that quote should be taken at face value. For the majority of the STL algorithms, you should not implement your predicate functor such that it has observable state (AKA "side effects"), because:


  • 未定义容器上的迭代顺序,

  • 该算法可自由复制函子,


无效的最简单的方法是强制执行此操作你自己定义 operator() const

The simplest way to enforce this upon yourself is to define operator() as const.

有例外,例如 for_each ,上面没有一个适用。你可以在这里免费使用有状态的函子。有关详情,请参阅此精彩文章: http://drdobbs.com/cpp/184403769

There are exceptions, such as for_each, for which none of the above apply. You are free to use stateful functors here. For more info, see this excellent article: http://drdobbs.com/cpp/184403769.

在后台,你的STL实现的作者可以随意写任何他们喜欢的 remove_if (和其他算法),只要它符合标准规定的要求。没有真正的理由担心太多,为什么你得到你所看到的行为,除了承认它是未定义的。如果你想知道具体细节,我只是看看在你使用的STL实现中 remove_if 的代码。

Behind the scenes, the authors of your STL implementation are free to write the remove_if (and other algorithms) any way they like, so long as it conforms to the requirements laid down by the standard. There's no real reason to worry too much about exactly why you're getting the behaviour you're seeing, beyond acknowledging that it's undefined. If you want to know the specifics, I would just take a look at the code for remove_if in the STL implementation that you're using.

至于你的旁注;这不是腐败,它只是一个工具如何 remove_if 工作(这将发生,即使一个有效的谓词)。唯一的要求是 pos left 的所有元素都是有效的(因为它们将被保留)。对 pos 向前存在的元素没有要求(请参见这里)。 ( 有效STL 的第32章) a> by Scott Meyers有很好的解释为什么 remove_if (等等)的行为像这样)。

As for your side-note; this is not "corruption", it's simply an artifact of how remove_if works (this would occur even for a valid predicate). The only requirement is that all the elements to the left of pos are valid (because they are to be retained). There are no requirements on what elements exist from pos onward (see here). (Chapter 32 of "Effective STL" by Scott Meyers has a good explanation of why remove_if (and so on) behave like this).

这篇关于状态函子STL:未定义的行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆