std::与VS2013相比,GCC 4.7.2中的MAP实现效率非常低
std::map implementation very inefficient in gcc 4.7.2 compared to VS2013?
有人可以帮助我理解std::map容器是如何实现的吗?我有一个包含原子成员的类,我不需要调用复制构造函数,所以我使用 c++11 delete 运算符来抑制复制构造函数的隐式生成。
MyCalss(const MyClass& a) = delete;
这在我的 Windows 构建中运行良好,但是在 Linux 中,我遇到了一个错误,通知我 std::map 类的 [] 运算符正在尝试调用已删除的函数。
Windows VS2013和Linux GCC 4.7.x的map实现之间似乎存在重大差异。这促使我做了一个关于如何将对象插入地图的实验。
我写了这个小示例程序:
#include <stdlib.h>
#include <stdio.h>
#include <map>
#include <iostream>
#include <string>
using namespace std;
class TestItem {
public:
TestItem () {
_name = "TestItem" + id();
cout << "Constructing " << _name << endl;
}
TestItem (const TestItem & other) {
_name = "TestItem " + id();
cout << "Copying " << other._name << " to new " << _name <<endl;
}
string id()
{
static int id = 0;
char buf[2];
sprintf_s(buf, "%d", id++);
return string(buf);
}
~TestItem(){
cout << "Destroying " << _name << endl;
}
void doStuff()
{
// stub
}
string _name;
};
void run()
{
cout << "making new obj" << endl;
TestItem a;
cout << endl << endl;
map<string, TestItem> TestItemMap;
cout << "Makeing new obj as part of a map insert" << endl;
TestItemMap["foo"].doStuff();
cout << endl << endl;
cout << "adding a value to the map" << endl;
TestItemMap["new foo key"] = a;
cout << endl << endl;
cout << "looking up a value that has already been inserted" << endl;
TestItem& b = TestItemMap["foo"];
cout << endl << endl;
}
int main(int argc, char** argv)
{
run();
}
在Windows中,当我运行此程序时,我得到以下输出:
making new obj
Constructing TestItem0
Making new obj as part of a map insert
Constructing TestItem1
adding a value to the map
Constructing TestItem2
looking up a value that has already been inserted
Destroying TestItem1
Destroying TestItem0
Destroying TestItem0
这是我在写作时希望在内部看到的
TestItemMap["foo"].doStuff();
我希望该映射将创建一个新的测试项实例,然后通过将树节点内部链接到新的测试项,将其插入到红黑树中。
但是,当我在 Linux 中运行相同的代码时,结果非常不同
making new obj
Constructing TestItem0
Making new obj as part of a map insert
Constructing TestItem1
Copying TestItem1 to new TestItem2
Copying TestItem2 to new TestItem3
Destroying TestItem2
Destroying TestItem1
adding a value to the map
Constructing TestItem4
Copying TestItem4 to new TestItem5
Copying TestItem5 to new TestItem6
Destroying TestItem5
Destroying TestItem4
looking up a value that has already been inserted
Destroying TestItem0
Destroying TestItem3
Destroying TestItem0
这将向我表明 [] 运算符正在创建 TestItem 的新实例,然后调用外部 map.insert() 函数,然后销毁新创建的 TestItem,这只能解释对复制构造函数的调用之一。gcc 中的 c++ stdlib 真的这么低效吗?
人们是否使用一些标准技巧来克服这个问题?
首先,我修复了那个可怕的sprintf_s
:
string id()
{
static int id = 0;
std::stringstream s;
s << id++;
return s.str();
}
并且还更改了您的"查找已插入的值"以实际执行它所说的操作[编辑:您也是如此:-)]
现在,在 C++03 模式下使用 g++ 4.8.1 进行编译,我得到的结果与您相似。但是用-std=c++11
编译,我得到
making new obj
Constructing TestItem0
Making new obj as part of a map insert
Constructing TestItem1
adding a value to the map
Constructing TestItem2
looking up a value that has already been inserted
Destroying TestItem0
Destroying TestItem1
Destroying TestItem0
MSVC 似乎自动使用 C++11 个功能(最有可能是移动语义)来提供很好的性能提升,而您需要明确告诉 g++ 也这样做。
这似乎是GCC 4.8修复的错误。
- 在这里它适用于GCC 4.8
- 在这里它无法使用 GCC 4.7 进行编译
- 使用字符数组作为 Map 中的键
- C++中 std::map 的运行时复杂度是多少?
- std::map, std::unordered_map - 缩小初始值设定项列表中的转换范围
- 视觉C++使用 map 来比较字符串中的每个单词
- 类中的 C++ 全局映射,不要打印 map 元素
- 找不到最新插入到 std::map 中的键
- C++ 中 std::map 的空间复杂度是多少?
- 在内存使用方面,c++ 中的 map 和 unordered_map 之间有什么区别吗?
- 有没有办法通过 LEMON 图形库中的 Map 值获取节点?
- 从C 中的MAP的随机子集创建新地图
- “无效的操作数是二进制表达式”当使用自定义结构作为C 中的MAP索引时
- 作为 Java 开发人员,了解 C++ 中的 Map
- C++使用Map中的Map检查键是否存在
- std::与VS2013相比,GCC 4.7.2中的MAP实现效率非常低
- 按值的降序对 C++ 中的 Map<string,int> 进行排序
- 如何在c++中高效地创建map中的map
- map中的map (map作为键)
- 将数据从CSV文件存储到c++中的MAP
- 在 c++ 中的 map< 字符串、<vector > 中查找矢量中的值<string>
- c++中的Map::const_iterator来映射