智能指针作为 unordered_map 键并通过引用进行比较
Smart pointers as unordered_map key and compare them by reference
我想使用 unordered_map
通过引用比较元素。我试图通过插入智能指针作为键来做到这一点(因为我不想使用原始指针)并实现 EqualFunction
来比较智能指针的底层引用。但是,地图无法正确找到元素。
#include <memory>
#include <unordered_map>
#include <iostream>
using namespace std;
class Node {};
typedef shared_ptr<Node> NodePtr;
struct HashFunction {
unsigned long operator()(const NodePtr& key) const {
return (unsigned long)key.get();
}
};
struct EqualFunction {
bool operator()(const NodePtr& t1, const NodePtr& t2) const {
return t1.get() == t2.get();
}
};
class Map
{
unordered_map<NodePtr, int, HashFunction, EqualFunction> map;
public:
void insert(NodePtr nodeToInsert, int val)
{
map.insert({nodeToInsert, val });
}
bool exist(NodePtr node) {
if (map.find(node) == map.end()) return false;
return true;
}
};
int main()
{
Node node; Map map;
auto nodePtr = make_shared<Node>(node);
map.insert(nodePtr, 1);
auto ptrToSameNode = make_shared<Node>(node);
if (map.exist(ptrToSameNode))
cout << "Node exists.";
else cout << "Node doesn't exist.";
}
以上代码打印 "Node doesn't exist" 即使我正在搜索相同的节点。
为什么你不想使用原始指针?使用它们。智能指针用于管理所有权,不用于指向在别处创建的对象。
using NodePtr = Node*;
struct HashFunction {
size_t operator()(const NodePtr& key) const { return (size_t)key; }
};
struct EqualFunction {
bool operator()(const NodePtr& t1, const NodePtr& t2) const { return t1 == t2; }
};
...
int main()
{
Node node; Map map;
auto nodePtr = &node;
map.insert(nodePtr, 1);
auto ptrToSameNode = &node;
if (map.exist(ptrToSameNode))
cout << "Node exists.";
else cout << "Node doesn't exist.";
}
正如@Piotr Skotnicki 在评论中所写,问题是您最初创建了 3 个 Node
对象,即 node
加上 2 个动态分配的复制 node
的对象(通过 make_shared
)。因此,您随后(按地址)比较了 Node
class.
的 2 个不同实例
或者,您可以使用 共享指针 ,但是您需要动态创建 Node
对象(而不是像代码中那样静态地在堆栈上创建)。如果你不希望你的 Map
到 "own" 包含的对象,你也可以使用 weak pointers,但是这样,你的比较会变慢(通过 "locking",即从弱指针创建共享指针)并且会有大量的运行时和内存开销。
我想使用 unordered_map
通过引用比较元素。我试图通过插入智能指针作为键来做到这一点(因为我不想使用原始指针)并实现 EqualFunction
来比较智能指针的底层引用。但是,地图无法正确找到元素。
#include <memory>
#include <unordered_map>
#include <iostream>
using namespace std;
class Node {};
typedef shared_ptr<Node> NodePtr;
struct HashFunction {
unsigned long operator()(const NodePtr& key) const {
return (unsigned long)key.get();
}
};
struct EqualFunction {
bool operator()(const NodePtr& t1, const NodePtr& t2) const {
return t1.get() == t2.get();
}
};
class Map
{
unordered_map<NodePtr, int, HashFunction, EqualFunction> map;
public:
void insert(NodePtr nodeToInsert, int val)
{
map.insert({nodeToInsert, val });
}
bool exist(NodePtr node) {
if (map.find(node) == map.end()) return false;
return true;
}
};
int main()
{
Node node; Map map;
auto nodePtr = make_shared<Node>(node);
map.insert(nodePtr, 1);
auto ptrToSameNode = make_shared<Node>(node);
if (map.exist(ptrToSameNode))
cout << "Node exists.";
else cout << "Node doesn't exist.";
}
以上代码打印 "Node doesn't exist" 即使我正在搜索相同的节点。
为什么你不想使用原始指针?使用它们。智能指针用于管理所有权,不用于指向在别处创建的对象。
using NodePtr = Node*;
struct HashFunction {
size_t operator()(const NodePtr& key) const { return (size_t)key; }
};
struct EqualFunction {
bool operator()(const NodePtr& t1, const NodePtr& t2) const { return t1 == t2; }
};
...
int main()
{
Node node; Map map;
auto nodePtr = &node;
map.insert(nodePtr, 1);
auto ptrToSameNode = &node;
if (map.exist(ptrToSameNode))
cout << "Node exists.";
else cout << "Node doesn't exist.";
}
正如@Piotr Skotnicki 在评论中所写,问题是您最初创建了 3 个 Node
对象,即 node
加上 2 个动态分配的复制 node
的对象(通过 make_shared
)。因此,您随后(按地址)比较了 Node
class.
或者,您可以使用 共享指针 ,但是您需要动态创建 Node
对象(而不是像代码中那样静态地在堆栈上创建)。如果你不希望你的 Map
到 "own" 包含的对象,你也可以使用 weak pointers,但是这样,你的比较会变慢(通过 "locking",即从弱指针创建共享指针)并且会有大量的运行时和内存开销。