每次在std::map中插入一个键为std::string的对时,它都会生成两个副本。您可以避免使用原始指针,但它是异常不安全的。有没有使用智能指针而不是原始指针的方法?
示例代码:
// To compile: g++ -std=c++0x exmaple.cpp -o example
#include <iostream>
#include <string>
#include <map>
#include <memory>
class StringSquealer: public std::string
{
public:
StringSquealer(const std::string s) : std::string(s) {}
StringSquealer(const StringSquealer&)
{
std::cout << "COPY-CONSTRUCTOR" << std::endl;
}
};
int main()
{
// Inefficient
std::map<StringSquealer,int> m1;
m1[StringSquealer("key")] = 1;
std::cout << "---" << std::endl;
// Exception-unsafe
std::map<StringSquealer*,int> m2;
m2[new StringSquealer("key")] = 1;
//Ideal??
std::map<std::unique_ptr<StringSquealer>,int> m3;
std::unique_ptr<StringSquealer> s(new StringSquealer("key"));
//!m3[std::move(s)] = 1; // No compile
}输出:
COPY-CONSTRUCTOR
COPY-CONSTRUCTOR
---发布于 2011-02-07 05:41:59
它的效率很低,因为你写错了类。C++0x提供了右值引用-你只是写了你的类,这样它就不能利用它们了。
class StringSquealer: public std::string
{
public:
StringSquealer(std::string&& s) : std::string(std::move(s)) {}
StringSquealer(const std::string& s) : std::string(s) {}
StringSquealer(const StringSquealer& s)
: std::string(s)
{
std::cout << "COPY-CONSTRUCTOR" << std::endl;
}
StringSquealer(StringSquealer&& s)
: std::string(std::move(s))
{
std::cout << "MOVE-CONSTRUCTOR" << std::endl;
}
};和unique_ptr作为关键?那怎么可能。你永远不会得到相同的unique_ptr- -即使你以某种方式获得了相同的指针,并从它构造了一个unique_ptr,你也会在比较完成后立即删除这个键。
发布于 2011-02-07 05:23:12
在我进入任何进一步的细节之前,请确保不要进行任何类型的优化,除非您确定制作副本的成本是如此之大,以至于您需要解决这个问题。将字符串作为键是很好和直观的,而且避免这种情况所需的代码也有些繁琐。
在地图中使用unique_ptr作为键确实可以工作,但我真的不认为这是一个好主意。这意味着,为了查询映射中的键,必须将字符串用作存储为unique_ptr的键。这意味着,除非您将所有字符串存储为unique_ptrs,否则您将需要为要查找的每个字符串创建一个副本。由于插入往往比查找少得多,因此这似乎是以牺牲常见情况为代价来优化不常见的情况。我强烈建议你不要这么做。
如果您确实希望摆脱不必要的复制,则可能需要考虑选择一个执行写入时复制的字符串实现。这样,制作字符串副本的成本是O(1),并且在插入过程中制作的两个副本将很便宜。这可能需要您在其他地方使用此字符串实现,并必须小心多线程问题,但如果您愿意,可以使其工作。
发布于 2011-02-07 05:26:53
这里有几个地方是错误的:
不应从std::string
中的关键字
您可以使用shared_ptr作为键,然后需要一个比较类来比较共享指针。
但是,最好只使用std::string作为键,除非它们是非常长的字符串,因此复制它们的成本很高。
顺便说一句,复制最昂贵的部分可能是分配而不是复制本身。为此,您可以考虑将basic_string与自定义分配器一起使用。
https://stackoverflow.com/questions/4916163
复制相似问题