C++ C++;关联容器-为什么';标准定义了交换和替换密钥的方法吗?

C++ C++;关联容器-为什么';标准定义了交换和替换密钥的方法吗?,c++,containers,associative,C++,Containers,Associative,我需要替换特定的键值,而value\u类型的其余部分保持不变。我实际上需要做的是,复制值,擦除条目,然后用更改的键值再次插入它。这绝对不好。我需要复制整个值类型两次,然后再次取消分配/分配 为什么标准没有定义这样的方法: // returns count of exchanged keys size_type exchange_key(key_type const& x, key_type const& y); // returns count of replaced keys

我需要替换特定的键值,而
value\u类型的其余部分保持不变。我实际上需要做的是,复制值,擦除条目,然后用更改的键值再次插入它。这绝对不好。我需要复制整个值类型两次,然后再次取消分配/分配

为什么标准没有定义这样的方法:

// returns count of exchanged keys
size_type exchange_key(key_type const& x, key_type const& y);
// returns count of replaced keys
size_type replace_key(key_type const& old_key, key_type const& new_key);

有什么我遗漏的吗?

我不知道为什么当初没有添加,我知道这太糟糕了。我猜他们只是添加了他们认为绝对必要的内容


我想我在某个地方读过提供这种能力的书

关联容器的实现方式不允许高效地更改“键”。为了使其显式化,它不提供替换键的方便方法。关联容器还必须移除并再次插入封盖下。

这是因为更改键可能会影响关联容器的结构。值得注意的是,
std::map
,这是一个典型的红黑树,一旦您修改一个键(例如,旋转子树),树结构大部分都会改变。在某些数据结构中,甚至这种动态更改也是不允许的。因此,在关联容器中公开此类操作作为标准是一项挑战


关于您所关心的开销,一旦您将value\u type作为指针或引用,删除/插入一对的开销就不会太大。

好吧,老实说,在屏幕后面,它将导致插入和删除操作,唯一的区别是不会复制值部分。虽然这似乎是您最关心的问题,但除非您的对象在复制方面非常繁重,否则在大型容器中,用于重新稳定已订购容器的更新操作无论如何都会很繁重

现在,这将需要一些重要的更改,但要比关联容器更进一步,我能看到的两个最重要的更改是:

  • std::pair类需要更新,因为您必须能够在不创建新对的情况下更新密钥(因为这也会复制value对象)
  • 您需要一个更新函数,该函数从树中删除一对,从1调用新逻辑,然后重新插入它
  • 我认为主要的问题在于第一个问题,因为
    std::pair
    目前实际上是一个非常简单的包装器,您的建议将删除该原则并增加一些(不必要的)复杂性。还要注意的是,call2实际上并没有添加新的功能,而是包装了一个系统,开发人员可以通过引用等轻松管理自己。如果他们将所有这些包装添加到std中,它将成为一个非常庞大的图书馆


    如果你想要这个原则,你应该寻找更复杂的库(可能boost有一些)。或者您应该简单地使用引用/共享\ptr作为您的值类型。

    我认为这是一个抽象问题。该标准并没有明确说明如何实现容器,它只指定了一些操作的最大复杂性,而将其余操作留给实现


    如果标准要添加一个
    replace_key
    功能,它还必须指定该功能的复杂性应与现有的擦除-插入组合不同。它如何做到这一点而不泄露实现细节?如果不能保证函数在所有实现上都更快,那么它就毫无用处了


    当您说它显然会更快时,您会对标准试图避免的实现细节做出假设。

    您可以先插入,然后删除。可能该值的副本少了一个(也可能更安全)。@visitor:在C++0x中,我认为(无需检查)可以将旧值移动到新值,然后擦除。异常安全,完全没有副本。@Steve Jessop-我不知道如何通过移动实现这一点,因为值和键在
    std::pair
    结构中组合在一起。我看不出这一对如何阻碍任何事情<代码>mymap.insert(创建配对(新密钥),移动(映射[旧密钥])
    ,或者类似的东西。然后把旧的擦掉。实际上,这不是异常安全的,因为如果插入失败,那么旧值已经被移动和丢弃,但是异常安全代码不适合此边距;-)或者
    std::pair
    没有移动元素的移动构造函数吗?@Steve Jessop-当然,std::pair有一个移动构造函数,但它取决于
    第二种类型的
    是否更有效。为什么不允许这样做?它实际上可以归结为一个删除/插入操作,而不复制value对象。我并不是说典型的STL会这样做。但是,一些数据结构,比如范围树,可能是静态的,不允许动态插入/删除,一旦构建完成。@Killian-您可以假设容器的内部结构是什么。该标准没有详细说明这些细节。@Bo:afaik擦除/插入是该标准的义务吗?“它还必须规定,这应该与现有的擦除-插入组合具有不同的复杂性”-它不可能做到这一点,复杂性比插入+删除的复杂性快,更换钥匙是不现实的。然而,我不同意标准机构认为便利功能必须具有更好的复杂性,才能值得添加到标准中。考虑<代码>运算符[]/COD>,它没有比等效查找+INSERT更好的复杂度。@ Steve Jessop -我认为他实际上的意思是,便利函数不应该比等价函数的组合更复杂。