请不要评论我应该如何通过引用等等。这段代码完全是实验性的。专注于非确定性行为。
标题听起来非常怀疑,我知道。
以下是发生的事情:
vector<int> find_permutation2(vector<int> v) {
int k = (int)v.size() - 1;
while(k >= 0 && v[k] >= v[k + 1])
k--;
if(k == -1) return vector<int>();
int i;
for(i = (int)v.size() - 1; i > k; i--) {
if(v[i] > v[k])
break;
}
vector<int> r(v);
std::swap(r[k], r[i]);
std::reverse(r.begin() + k + 1, r.end());
return r;
}
int main() {
vector<int> foo = {2,3,4,1,0};
vector<int> bar = find_permutation2(foo);
default_random_engine g;
uniform_int_distribution<int> dist(5,10);
for(int i = 0; i < 10000; i++) {
int size = dist(g);
vector<int> p(size);
iota(p.begin(), p.end(), 0);
shuffle(p.begin(), p.end(), g);
//
// BREAKPOINT ON THE FOLLOWING LINE
// I continue until p == {2,3,4,1,0}
//
vector<int> r = find_permutation2(p);
vector<int> pc = vector<int>(p);
bool res = std::next_permutation(pc.begin(), pc.end());
if(res)
assert(pc == r);
else
assert(r.size() == 0);
}
现在请检查我的LLDB输出以查询某些查询(注意产生不同的输出):
(lldb) expr find_permutation2(p)
(std::__1::vector<int, std::__1::allocator<int> >) $0 = size=5 {
[0] = 2
[1] = 4
[2] = 0
[3] = 1
[4] = 3
}
(lldb) expr find_permutation2(p)
(std::__1::vector<int, std::__1::allocator<int> >) $2 = size=5 {
[0] = 2
[1] = 3
[2] = 4
[3] = 1
[4] = 0
}
(lldb) expr find_permutation2(foo)
(std::__1::vector<int, std::__1::allocator<int> >) $0 = size=5 {
[0] = 2
[1] = 3
[2] = 4
[3] = 1
[4] = 0
}
(lldb) expr find_permutation2(foo)
(std::__1::vector<int, std::__1::allocator<int> >) $2 = size=5 {
[0] = 2
[1] = 4
[2] = 0
[3] = 1
[4] = 3
}
BTW,它不仅仅是LLDB。如果我运行代码,断言有时会失败,有时在给定的输入{2,3,4,1,0}
上不会失败。上述两者之间的输出似乎完全随机。
编辑 - 明确的问题
有人可以告诉我为什么我为相同的函数调用获取相同输入的不同输出?
答案 0 :(得分:5)
在此代码中
int k = (int)v.size() - 1;
while(k >= 0 && v[k] >= v[k + 1])
v[k+1]
在第一次迭代时引用超出v
末尾的元素,这会给出未定义的行为。