C++ `sTD :: set_difference`与不同的编译器的不同输出
现在,我有下面的代码,仅测试std :: set_difference
在标准库中:
#include <algorithm>
#include <vector>
#include <memory>
#include <iostream>
struct Node{
public:
Node(int x) : foo(x){}
int foo = 10;
};
using NodePtrVec = std::vector<std::shared_ptr<Node>>;
using NodePtr = std::shared_ptr<Node>;
using IntVec = std::vector<int>;
int main(void){
// pointer test
NodePtr inA_1 = std::make_shared<Node>(1);
NodePtr inA_2 = std::make_shared<Node>(11);
NodePtr inA_3 = std::make_shared<Node>(111);
NodePtr inB_1 = std::make_shared<Node>(2);
NodePtr inB_2 = std::make_shared<Node>(22);
NodePtr inB_3 = std::make_shared<Node>(222);
NodePtr both_1 = std::make_shared<Node>(3);
NodePtr both_2 = std::make_shared<Node>(33);
NodePtrVec a{inA_1,inA_2,inA_3,both_1,both_2};
NodePtrVec b{inB_1,inB_2,inB_3,both_1,both_2};
NodePtrVec c{};
std::set_difference(a.begin(), a.end(), b.begin(), b.end(),
std::back_inserter(c));
for(const auto& tmp : c){
std::cout << tmp->foo << std::endl;
}
// int test
std::cout << "int test" << std::endl;
IntVec int_a = {1,5,4,2,3};
IntVec int_b = {1,10,7};
IntVec int_c;
std::set_difference(int_a.begin(), int_a.end(), int_b.begin(), int_b.end(),
std::back_inserter(int_c));
for(const auto& tmp : int_c){
std::cout << tmp << std::endl;
}
}
当我使用clang/gcc编译时,我得到了输出:
ASM generation compiler returned: 0
Execution build compiler returned: 0
Program returned: 0
1
11
111
int test
5
4
2
3
update update 假设node
是我要做的一些动作。
#include <algorithm>
#include <vector>
#include <memory>
#include <iostream>
struct Node{
public:
Node(int x) : foo(x){}
int foo = 10;
};
using NodePtrVec = std::vector<std::shared_ptr<Node>>;
using NodePtr = std::shared_ptr<Node>;
using IntVec = std::vector<int>;
int main(void){
// pointer test
NodePtr inA_1 = std::make_shared<Node>(1);
NodePtr inA_2 = std::make_shared<Node>(11);
NodePtr inA_3 = std::make_shared<Node>(111);
// total elements
NodePtrVec total{inA_1,inA_2,inA_3};
// sub set of the elements
NodePtrVec sub{inA_2};
NodePtrVec c{};
// just want to get the compliment of the sub in total
// as expected, c should be {inA_1,inA_3}
std::set_difference(total.begin(), total.end(), sub.begin(), sub.end(),
std::back_inserter(c));
for(const auto& tmp : c){
std::cout << tmp->foo << std::endl;
}
}
我要实际使用的源代码案例( 它实际上对应于 std :: set_difference 。 https://godbolt.org/z/mnvbke97e 但是,当我选择MSVC时,我会收到不同的输出(检查链接: https://godbolt.org.org/z/nyre1oneo ):
example.cpp
ASM generation compiler returned: 0
example.cpp
Execution build compiler returned: 0
Program returned: 0
1
11
111
3
33
int test
5
4
2
3
糟糕,我们得到了意外的结果!顺便说一句,当我更改MSVC编译器版本时,输出似乎会发生变化。但为什么?
Now, I have code below which just tests the std::set_difference
in the standard library:
#include <algorithm>
#include <vector>
#include <memory>
#include <iostream>
struct Node{
public:
Node(int x) : foo(x){}
int foo = 10;
};
using NodePtrVec = std::vector<std::shared_ptr<Node>>;
using NodePtr = std::shared_ptr<Node>;
using IntVec = std::vector<int>;
int main(void){
// pointer test
NodePtr inA_1 = std::make_shared<Node>(1);
NodePtr inA_2 = std::make_shared<Node>(11);
NodePtr inA_3 = std::make_shared<Node>(111);
NodePtr inB_1 = std::make_shared<Node>(2);
NodePtr inB_2 = std::make_shared<Node>(22);
NodePtr inB_3 = std::make_shared<Node>(222);
NodePtr both_1 = std::make_shared<Node>(3);
NodePtr both_2 = std::make_shared<Node>(33);
NodePtrVec a{inA_1,inA_2,inA_3,both_1,both_2};
NodePtrVec b{inB_1,inB_2,inB_3,both_1,both_2};
NodePtrVec c{};
std::set_difference(a.begin(), a.end(), b.begin(), b.end(),
std::back_inserter(c));
for(const auto& tmp : c){
std::cout << tmp->foo << std::endl;
}
// int test
std::cout << "int test" << std::endl;
IntVec int_a = {1,5,4,2,3};
IntVec int_b = {1,10,7};
IntVec int_c;
std::set_difference(int_a.begin(), int_a.end(), int_b.begin(), int_b.end(),
std::back_inserter(int_c));
for(const auto& tmp : int_c){
std::cout << tmp << std::endl;
}
}
When I compile this with Clang/GCC, I got outputs:
ASM generation compiler returned: 0
Execution build compiler returned: 0
Program returned: 0
1
11
111
int test
5
4
2
3
UPDATE
the source code case I want to actually use (suppose Node
are some actions I will do. So these actions will happen in the order of total
):
#include <algorithm>
#include <vector>
#include <memory>
#include <iostream>
struct Node{
public:
Node(int x) : foo(x){}
int foo = 10;
};
using NodePtrVec = std::vector<std::shared_ptr<Node>>;
using NodePtr = std::shared_ptr<Node>;
using IntVec = std::vector<int>;
int main(void){
// pointer test
NodePtr inA_1 = std::make_shared<Node>(1);
NodePtr inA_2 = std::make_shared<Node>(11);
NodePtr inA_3 = std::make_shared<Node>(111);
// total elements
NodePtrVec total{inA_1,inA_2,inA_3};
// sub set of the elements
NodePtrVec sub{inA_2};
NodePtrVec c{};
// just want to get the compliment of the sub in total
// as expected, c should be {inA_1,inA_3}
std::set_difference(total.begin(), total.end(), sub.begin(), sub.end(),
std::back_inserter(c));
for(const auto& tmp : c){
std::cout << tmp->foo << std::endl;
}
}
OK, this seems good and it actually correspond to the std::set_difference., check the link:https://godbolt.org/z/MnvbKE97e
But when I choose MSVC, I got different outputs (check the link: https://godbolt.org/z/nYre1Eono):
example.cpp
ASM generation compiler returned: 0
example.cpp
Execution build compiler returned: 0
Program returned: 0
1
11
111
3
33
int test
5
4
2
3
oops, we got unexpected results! By the way, It seems outputs will change when I changed the MSVC compiler version. But Why?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
必须对
set_difference
进行分类。您的没有分类。The ranges input to
set_difference
have to be sorted. Yours are not sorted.如注释中所述,在您的情况下,
std :: set_difference
正在比较shared_ptr
,而不是指向指向的值。当然,它仍然可以工作,因为std :: shared_ptr
具有operator ==
仅比较原始指针的地址,但是 set_difference 是您的范围是分类的,如果您查看MSVC的输出,则不是这样(外观就像偶然地分配记忆的升序顺序一样,导致了分类的向量)。首先对矢量进行排序:然后您将获得所需的输出也带有MSVC。甚至更好,使用自定义比较器对向量进行分类,然后使用自定义比较器计算设置差异,这将更加惯用:
编辑
我只是在您实际上想比较指针的注释中阅读,而不是它们指向的值。在这种情况下,我的答案的第一部分是最相关的。
edit2:
然后您必须复制向量,对矢量进行排序并计算差异,或者在您的情况下不能使用
std :: Set_difference
。如果您的操作相对顺序需要保留,请尝试以下操作:迭代a并将元素插入c,如果它不存在。 :: unordered_set 用于您的容器B,因为它具有恒定的时间查找(平均):Like mentioned in the comments, in your case
std::set_difference
is comparingshared_ptr
, not the values your pointers are pointing to. It could still work of course, becausestd::shared_ptr
hasoperator==
that just compares the addresses of raw pointers, however the requirement of set_difference is that your ranges are sorted, which is not the case if you look at the output of MSVC (looks like clang by chance allocated memory in ascending order, which resulted in sorted vectors). Sort your vectors first:and you will get your desired output also with MSVC. Or even better, sort your vectors using custom comparator, and then calculate the set difference using custom comparator, which will be more idiomatic:
EDIT
I just read in the comments that you actually want to compare the pointers, not the values they point to. In this case, first part of my answer is the most relevant.
EDIT2:
Then you either have to copy your vector, sort it, and calculate the difference, or you cannot use
std::set_difference
in your situation. If the relative order of your actions needs to be preserved, maybe try this: iterate over A and insert the element to C if it does not exist in B. Since only order of elements in A needs to be preserved, usestd::unordered_set
for your container B, because it has constant-time lookup (on average):