为什么operator()在我的程序中被调用了两次?
Why operator () is called twice in my program?
#include <unordered_set>
#include <stdio.h>
int hcount=0;
struct A{
int i=0;
A(){}
A(const A&a) :i(a.i){}
A(int const & i):i(i) {
printf("A ctor i=%d\n", i);
}
A&operator=(A &&a){
this->i= a.i;
return (*this);
}
bool operator==(A const &rhs) const {
printf("A optor== i=%d\n", this->i);
return rhs.i == this->i;
}
};
namespace std{
template<>
struct hash<A> {
hash() {
hcount=0;
}
hash(int t) {
hcount=t;
}
std::size_t operator()(A const &a) const {
++hcount;
printf("hash: hcount=%d a.i=%d\n", hcount, a.i);
return a.i;
};
};
}
int main(int argc, char **argv)
{
std::initializer_list< A > test={
{A(1)},
{A(2)}
};
std::unordered_multiset<A> u(4, std::hash<A>(5) );
printf("1 ---------test.size is %d hcount is %d\n", test.size(), hcount);
u.insert(test.begin(), test.end() );
printf("2------------test.size is %d hcount is %d\n", test.size(), hcount);
return 0;
}
运行代码,我得到:
A ctor i=1
A ctor i=2
1 ---------test.size is 2 hcount is 5
hash: hcount=6 a.i=1 //operator() is called once for A(1)
hash: hcount=7 a.i=1 //operator() is called twice for A(1)
hash: hcount=8 a.i=2
hash: hcount=9 a.i=2
2------------test.size is 2 hcount is 9
我不明白为什么在 insert() 期间调用了两次 operator()。
应该只调用一次吗?
感谢分享您的想法。
看来结果取决于每个编译器。 vc++ 和 g++ 的标准输出如下:
A ctor i=1
A ctor i=2
1 ---------test.size is 2 hcount is 5
hash: hcount=6 a.i=1
hash: hcount=7 a.i=2
2------------test.size is 2 hcount is 7
clang++的标准输出(和你的一样)如下:
A ctor i=1
A ctor i=2
1 ---------test.size is 2 hcount is 5
hash: hcount=6 a.i=1
hash: hcount=7 a.i=1
hash: hcount=8 a.i=2
hash: hcount=9 a.i=2
2------------test.size is 2 hcount is 9
测试您的代码
据推测,您正在使用 libc++。带有 libc++ 的 Clang 表现出这种行为。带有 libstdc++ 的 Clang 没有。
initializer list insert calls the range insert which calls __hashtable::__insert_multi which calls __construct_node which hashes, after which __insert_multi calls __node_insert_multi which also hashes.
我在标准中没有看到任何相关内容可以防止这种情况发生,所以它可能只是“QoI”。
#include <unordered_set>
#include <stdio.h>
int hcount=0;
struct A{
int i=0;
A(){}
A(const A&a) :i(a.i){}
A(int const & i):i(i) {
printf("A ctor i=%d\n", i);
}
A&operator=(A &&a){
this->i= a.i;
return (*this);
}
bool operator==(A const &rhs) const {
printf("A optor== i=%d\n", this->i);
return rhs.i == this->i;
}
};
namespace std{
template<>
struct hash<A> {
hash() {
hcount=0;
}
hash(int t) {
hcount=t;
}
std::size_t operator()(A const &a) const {
++hcount;
printf("hash: hcount=%d a.i=%d\n", hcount, a.i);
return a.i;
};
};
}
int main(int argc, char **argv)
{
std::initializer_list< A > test={
{A(1)},
{A(2)}
};
std::unordered_multiset<A> u(4, std::hash<A>(5) );
printf("1 ---------test.size is %d hcount is %d\n", test.size(), hcount);
u.insert(test.begin(), test.end() );
printf("2------------test.size is %d hcount is %d\n", test.size(), hcount);
return 0;
}
运行代码,我得到:
A ctor i=1
A ctor i=2
1 ---------test.size is 2 hcount is 5
hash: hcount=6 a.i=1 //operator() is called once for A(1)
hash: hcount=7 a.i=1 //operator() is called twice for A(1)
hash: hcount=8 a.i=2
hash: hcount=9 a.i=2
2------------test.size is 2 hcount is 9
我不明白为什么在 insert() 期间调用了两次 operator()。 应该只调用一次吗?
感谢分享您的想法。
看来结果取决于每个编译器。 vc++ 和 g++ 的标准输出如下:
A ctor i=1
A ctor i=2
1 ---------test.size is 2 hcount is 5
hash: hcount=6 a.i=1
hash: hcount=7 a.i=2
2------------test.size is 2 hcount is 7
clang++的标准输出(和你的一样)如下:
A ctor i=1
A ctor i=2
1 ---------test.size is 2 hcount is 5
hash: hcount=6 a.i=1
hash: hcount=7 a.i=1
hash: hcount=8 a.i=2
hash: hcount=9 a.i=2
2------------test.size is 2 hcount is 9
测试您的代码
据推测,您正在使用 libc++。带有 libc++ 的 Clang 表现出这种行为。带有 libstdc++ 的 Clang 没有。
initializer list insert calls the range insert which calls __hashtable::__insert_multi which calls __construct_node which hashes, after which __insert_multi calls __node_insert_multi which also hashes.
我在标准中没有看到任何相关内容可以防止这种情况发生,所以它可能只是“QoI”。