根据草案
如果给定相同的输入,表达式导致相同的输出.则表达式为equality-preserving .
和
.稳定的:对于具有相同输入对象的表达式的两个计算值必须具有相同的输出,而不需要对这些输入对象进行任何显式的干预修改。
强调我的。
发布于 2019-09-26 05:20:56
对于修改其输入的操作,两者将是不同的。
// stable and equality preserving
int foo(int a, int b) {
return a + b;
}
// equality preserving, but not stable:
int bar(int a, int &b) {
auto ret = a + b;
++b;
return ret;
}例如:
int x = 1, y = 2;
int z = foo(x, y); // produces 3
int z2 = foo(x, y); // still produces 3
int zz = bar(x, y); // produces 3
int zz2 = bar(x, y); // produces 4至于一些稳定但不平等的东西,是的,这也是可能的(对于“平等”的一些定义)。
对于一个简单的例子,请考虑如下所示:
struct foo {
int bar;
// they're all equal, just some are more equal than others
bool operator==(foo const &) const { return true; }
};
int operator+(foo a, foo b) { return a.bar + b.bar; }
foo a{1};
foo b{2};
foo c{3};
// obviously both true
assert(a == b);
assert(b == c);
int x = a + b;
int y = b + c;
assert(x != y); // of course 1 + 2 != 2 + 3;发布于 2021-05-05 22:08:00
批准的答案是不正确的。这一职能:
int foo(int a, int b) {
return a + b;
}确实是维护平等和稳定的。但这一功能也是如此:
int bar(int a, int &b) {
auto ret = a + b;
++b;
return ret;
}两者之间的实际区别是foo是正则的(cf概念regular_invocable),而bar不是。
保持等式但不稳定的函数的一个例子是:
int b = 0; // assume accessible by other threads
int zip(int a) {
auto ret = a + b;
++b;
return ret;
}这是平等保持,因为平等保存纯粹是静态的,而且在任何给定的时间,zip都会给出相同的结果,具有相同的输入。
但是,zip并不稳定,因为稳定性是动态的,在不同的时间,zip可能会在相同的输入下给出不同的结果。
(如果全局变量b在调用之间没有变化,那么它将给出一个不同的结果。但是,如果另一个线程减少了b,并且没有发生其他更改,它将提供相同的结果。)
(如果没有其他线程能够访问b变量,尽管这实际上是如何实现的,那么我们就具有稳定性,因为我们可以观察到“显式干预修改”。这就是为什么标准提到稳定性禁止“自发”变化,也就是波动,以及其他执行线程的变化,等等。Cf concepts.lib.general.equality)
还要注意的是,等式保持并不取决于相等操作符的可用性(而equality_comparable概念实际上需要平等保存)。等式没有明确定义,但应该被视为可替换性或不可区分性,这是标准经常提到的,例如在strong_ordering中。
如果不保持等式,函数就不可能是稳定的,因为稳定性是静态平等保持概念的动态扩展。
https://stackoverflow.com/questions/58109930
复制相似问题