STL地图价值构造函数

时间:2010-09-22 16:27:49

标签: c++ stl

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

我注意到以下代码,其中x是X类型的对象,stlMap是std :: map类型的地图:

stlMap["test"] = x;

以下结果被称为:

  1. X默认构造函数
  2. X复制构造函数
  3. X复制构造函数
  4. X析构函数
  5. X析构函数
  6. X赋值构造函数
  7. X析构函数
  8. 为什么要创建这么多X对象?

    这是时间和记忆的低效使用吗?

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

5 个答案:

答案 0 :(得分: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 ++上将事情归结为:

  1. X copy constructor
  2. X copy constructor
  3. X析构函数
  4. 编辑:根据ArunSaha的建议,更新了测试。 insert()输出未更改,而赋值序列如下所示:

    1. X默认构造函数
    2. X copy constructor
    3. X copy constructor
    4. X析构函数
    5. X析构函数
    6. X copy-assignment operator

答案 1 :(得分:3)

STL容器具有复制语义,因此您观察到的是典型的。

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

答案 2 :(得分: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

答案 3 :(得分:0)

STL的工作原理是复制和分配。因此需要进行一些复制和分配。关于为什么这么多的问题,找到这种方法的一种方法是将断点放在X代码中的适当位置,并在调试器中运行该程序。

以当前方式,std::map正在为X进行内存管理。如果切换到使用X*,则必须自己进行内存管理。我发现前者适合大多数情况。

答案 4 :(得分:0)

启用优化时,构造和销毁的顺序是否不同?许多编译器在优化时可以省略这些语句中涉及的临时对象。我猜想在优化时输出会涉及更少的对象。

C ++ 0x通过移动构造函数大大改善了这种情况。如果您的类X有一个移动构造函数(看起来像X x(X&& m) { ... }),那么您可以将语句更改为stlMap["test"] = std::move(x);。该语句基本上等同于构造单个X然后将其移动到所有权如果你没有找到C ++ 0x移动语义的一些文章,这是有用的东西。