【发布时间】:2020-06-06 13:08:38
【问题描述】:
在 C++ 中,可以从地图中窃取我以后不再需要的资源吗?更准确地说,假设我有一个带有std::string 键的std::map,并且我想通过使用std::move 窃取maps 键的资源来构造一个向量。请注意,对密钥的这种写访问会破坏map 的内部数据结构(密钥的顺序),但之后我不会使用它。
问题:我是否可以毫无问题地执行此操作,或者这会导致意外的错误,例如 map 的析构函数中的错误,因为我以不打算使用 std::map 的方式访问它为了?
这是一个示例程序:
#include<map>
#include<string>
#include<vector>
#include<iostream>
using namespace std;
int main(int argc, char *argv[])
{
std::vector<std::pair<std::string,double>> v;
{ // new scope to make clear that m is not needed
// after the resources were stolen
std::map<std::string,double> m;
m["aLongString"]=1.0;
m["anotherLongString"]=2.0;
//
// now steal resources
for (auto &p : m) {
// according to my IDE, p has type
// std::pair<const class std::__cxx11::basic_string<char>, double>&
cout<<"key before stealing: "<<p.first<<endl;
v.emplace_back(make_pair(std::move(const_cast<string&>(p.first)),p.second));
cout<<"key after stealing: "<<p.first<<endl;
}
}
// now use v
return 0;
}
它产生输出:
key before stealing: aLongString
key after stealing:
key before stealing: anotherLongString
key after stealing:
编辑:我想对大地图的全部内容执行此操作,并通过这种资源窃取来保存动态分配。
【问题讨论】:
-
这个“偷”的目的是什么?从地图中删除元素?那么为什么不简单地这样做(从地图中删除元素)?此外,修改
const值是总是 UB。 -
显然会导致严重的bug!
-
不是直接回答您的问题,而是:如果您不返回向量而是返回一个范围或一对迭代器怎么办?那将完全避免复制。在任何情况下,您都需要基准来跟踪优化的进度,并需要一个分析器来查找热点。
-
@ALX23z 你有这个声明的来源吗?我无法想象复制指针比复制整个内存区域更昂贵。
-
@SebastianHoffmann 在最近的 CppCon 上提到过,但不确定是在哪个谈话上。问题是
std::string有短字符串优化。这意味着在复制和移动方面有一些重要的逻辑,而不仅仅是指针交换,而且大部分时间移动意味着复制 - 以免您处理相当长的字符串。无论如何,统计差异很小,通常它肯定会根据执行的字符串处理类型而有所不同。
标签: c++ move-semantics