首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >避免复制没有原始指针的映射键

避免复制没有原始指针的映射键
EN

Stack Overflow用户
提问于 2011-02-07 05:13:39
回答 3查看 886关注 0票数 3

每次在std::map中插入一个键为std::string的对时,它都会生成两个副本。您可以避免使用原始指针,但它是异常不安全的。有没有使用智能指针而不是原始指针的方法?

示例代码:

代码语言:javascript
复制
// 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
}

输出:

代码语言:javascript
复制
COPY-CONSTRUCTOR
COPY-CONSTRUCTOR
---
EN

回答 3

Stack Overflow用户

发布于 2011-02-07 05:41:59

它的效率很低,因为你写错了类。C++0x提供了右值引用-你只是写了你的类,这样它就不能利用它们了。

代码语言:javascript
复制
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,你也会在比较完成后立即删除这个键。

票数 7
EN

Stack Overflow用户

发布于 2011-02-07 05:23:12

在我进入任何进一步的细节之前,请确保不要进行任何类型的优化,除非您确定制作副本的成本是如此之大,以至于您需要解决这个问题。将字符串作为键是很好和直观的,而且避免这种情况所需的代码也有些繁琐。

在地图中使用unique_ptr作为键确实可以工作,但我真的不认为这是一个好主意。这意味着,为了查询映射中的键,必须将字符串用作存储为unique_ptr的键。这意味着,除非您将所有字符串存储为unique_ptrs,否则您将需要为要查找的每个字符串创建一个副本。由于插入往往比查找少得多,因此这似乎是以牺牲常见情况为代价来优化不常见的情况。我强烈建议你不要这么做。

如果您确实希望摆脱不必要的复制,则可能需要考虑选择一个执行写入时复制的字符串实现。这样,制作字符串副本的成本是O(1),并且在插入过程中制作的两个副本将很便宜。这可能需要您在其他地方使用此字符串实现,并必须小心多线程问题,但如果您愿意,可以使其工作。

票数 2
EN

Stack Overflow用户

发布于 2011-02-07 05:26:53

这里有几个地方是错误的:

不应从std::string

  • You派生类不应将unique_ptr用作地图

中的关键字

您可以使用shared_ptr作为键,然后需要一个比较类来比较共享指针。

但是,最好只使用std::string作为键,除非它们是非常长的字符串,因此复制它们的成本很高。

顺便说一句,复制最昂贵的部分可能是分配而不是复制本身。为此,您可以考虑将basic_string与自定义分配器一起使用。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4916163

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档