2010-09-22 108 views
3

我有一个类X,我想将它放入std :: map类型的STL映射中。 STL地图需要将X存储在内存中,所以我正在寻找一种有效的(运行时间和内存)方式来创建X并将其存储在地图中。STL映射值构造函数

我注意到,下面的代码,其中x是X型和stlMap的一个目的是地图上的类型的std ::地图:

stlMap["test"] = x; 

结果在下面被称为:

  1. X默认的构造函数
  2. X拷贝构造函数
  3. X拷贝构造函数
  4. X的析构函数
  5. X的析构函数
  6. X分配构造
  7. X的析构函数

为什么要创建这么多的X对象?

它是时间和内存的低效使用吗?

有没有更好的方法将对象放入地图?也许改变地图是一个字符串映射到x *?

+0

你试过开启优化我会删除很多这些。 – 2010-09-22 18:05:38

回答

5

尝试stlMap.insert(map<string, X>::value_type("test", x))

#include <iostream> 
#include <string> 
#include <map> 

using namespace std; 

class X 
{ 
public: 
X() { cout << "X default constructor" << endl; } 
~X() { cout << "X destructor" << endl; } 
X(const X& other) { cout << "X copy constructor" << endl; } 
X& operator=(const X& other) { cout << "X copy-assignment operator" << endl; } 
int x; 
}; 


int main() 
{ 
X x; 
map< string, X > stlMap; 

cout << "INSERT BEGIN" << endl; 
stlMap.insert(map< string, X >::value_type("test", x)); 
cout << "INSERT END" << endl; 
stlMap.clear(); 
cout << "ASSIGN BEGIN" << endl; 
stlMap["test"] = x; 
cout << "ASSIGN END" << endl; 

return 0; 
} 

在我的G ++是whittles下来到:

  1. X拷贝构造函数
  2. X拷贝构造函数
  3. X的析构函数

编辑:每ArunSaha的uggestion,更新了测试。插入()输出不变,而分配顺序是这样的:

  1. X默认的构造函数
  2. X拷贝构造函数
  3. X拷贝构造函数
  4. X的析构函数
  5. X的析构函数
  6. X复制赋值运算符
+1

+1:我在想同一个实验......你可以在复制赋值运算符中添加一个'cout'并重新运行实验吗? – Arun 2010-09-22 18:19:56

+0

@ArunSaha:好抓,知道我忘了东西:)更新。 – genpfault 2010-09-22 19:04:49

+0

完美,谢谢。我会尝试value_type操作。 – 2010-09-23 12:50:58

3

STL容器有复制语义,所以你观察到的是典型的。

您可以改用指针,但可以通过使用智能指针(以少量开销为代价)避免相关的内存管理痛苦。

+0

+1从地图重定向 2010-09-22 16:53:29

0

STL在复制和分配的基础上工作。因此预计会有一些复制和分配。关于为什么有这么多的一种方法是在X代码中将断点放在合适的位置,然后在调试器中运行程序。

以目前的方式,std::map正在做X的内存管理。如果你切换到使用,那么你必须自己做内存管理。我发现前者在大多数情况下都适用。

0

是建造顺序和destr当您启用优化时,哪些因素会有所不同?许多编译器在优化时可以省略涉及这些语句的临时对象。我猜测输出在优化时会涉及更少的对象。

C++ 0x大大改善了这种情况,移动构造函数。如果你的类X有一个移动构造函数(看起来像X x(X&& m) { ... },那么你可以把你的语句改成stlMap["test"] = std::move(x);。这个语句基本上等同于构造一个X然后把它移到地图的所有权上。如果你不避让++ 0x中移动的语义,它是有用的东西

1

使用此作为参考。

#include <iostream> 
#include <map> 

class X 
{ 
    public: 
    X()     { std::cout << "Default Construct\n";} 
    ~X()     { std::cout << "Destroy\n";} 
    X(X const&)   { std::cout << "Copy Construct\n";} 
    X& operator=(X const&) { std::cout << "Assignment\n";} 
}; 


int main() 
{ 
    std::map<int,X>  store; 
    X     x; 
    X     y; 

    std::cout << "Inserting x\n"; 
    store[1] = x; 
    std::cout << "Finished Insert\n"; 
    std::cout << "Inserting y\n"; 
    store[1] = y; 
    std::cout << "Finished Insert\n"; 
} 

运行,我们得到以下的输出:

Default Construct     Building X 
Default Construct     Building Y 
Inserting x       ---- Start of an insert 
Default Construct     -------- Work to insert an item that is not in the map 
Copy Construct       
Copy Construct      
Destroy        
Destroy        -------- Finished work to insert a new item 
Assignment       Assign x into the internal object 
Finished Insert      ---- Done 
Inserting y       ---- Start of an insert 
Assignment       Assign y onto the internal object. 
Finished Insert      ---- Done 
Destroy        Destroy y 
Destroy        Destroy x 
Destroy        Destroy map containing one X