简体   繁体   English

STL地图价值构造函数

[英]STL Map Value Constructors

I have a class X that I would like to put into an STL map of type std::map. 我有一个类X,我想将其放入std :: map类型的STL映射中。 An STL map needs to have X stored in memory somewhere so I'm looking for an efficient (run time and memory) way to create X and store it in the map. STL映射需要将X存储在某个内存中,所以我正在寻找一种有效的(运行时和内存)方式来创建X并将其存储在地图中。

I noticed that the following code where x is an object of type X and stlMap is a map of type std::map: 我注意到下面的代码,其中x是X类型的对象,stlMap是std :: map类型的映射:

stlMap["test"] = x;

Results in the following being called: 调用以下结果:

  1. X default constructor X默认构造函数
  2. X Copy constructor X复制构造函数
  3. X Copy constructor X复制构造函数
  4. X destructor X析构函数
  5. X destructor X析构函数
  6. X assignment constructor X赋值构造函数
  7. X destructor X析构函数

Why are so many X objects being created? 为什么要创建这么多X对象?

Is it an inefficient use of time and memory? 这是时间和记忆的低效利用吗?

Is there a better way to put an object into a map? 有没有更好的方法将对象放入地图? Maybe changing the map to be a map of strings to x*? 也许将地图更改为x *的字符串映射?

Try stlMap.insert( map<string, X>::value_type("test", x) ) : 尝试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;
}

On my g++ that whittles things down to: 在我的g ++上,将事情归结为:

  1. X copy constructor X拷贝构造函数
  2. X copy constructor X拷贝构造函数
  3. X destructor X析构函数

EDIT: Per ArunSaha's suggestion, updated the test. 编辑:Per ArunSaha的建议,更新了测试。 The insert() output is unchanged, while the assignment sequence looks like this: insert()输出未更改,而赋值序列如下所示:

  1. X default constructor X默认构造函数
  2. X copy constructor X拷贝构造函数
  3. X copy constructor X拷贝构造函数
  4. X destructor X析构函数
  5. X destructor X析构函数
  6. X copy-assignment operator X副本赋值运算符

STL containers have copy semantics, so what you observe is typical. STL容器具有复制语义,因此您观察到的是典型的。

You could use pointers instead, but you can avoid the associated memory-management pain by using smart pointers (at the cost of a small amount of overhead). 您可以使用指针,但是您可以通过使用智能指针(以少量开销为代价)来避免相关的内存管理难题。

Using this as a reference: 以此为参考:

#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";
}

Running we get the following output: 运行我们得到以下输出:

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

STL works on the basis of copying and assigning. STL的工作原理是复制和分配。 So some amount of copying and assignment is expected. 因此需要进行一些复制和分配。 On the question of why so many, one way to find that is to put breakpoints at appropriate positions in X code, and run the program in debugger. 关于为什么这么多的问题,找到一种方法是在X代码中将断点放在适当的位置,并在调试器中运行程序。

In the current way, std::map is doing the memory management for X . 在当前的方式中, std::map正在为X进行内存管理。 If you switch to using X* , then you have to do the memory management yourself. 如果切换到使用X* ,则必须自己进行内存管理。 I find the former suitable in most cases. 我发现前者适合大多数情况。

Is the order of construction and destruction different when you enable optimizations? 启用优化时,构造和销毁的顺序是否不同? Many compilers can omit temporary objects involved in such statements when optimizing. 许多编译器在优化时可以省略这些语句中涉及的临时对象。 I'd guess the output would involve fewer objects when optimized. 我猜测输出在优化时会涉及更少的对象。

C++0x improves the situation considerably with move constructors . C ++ 0x通过移动构造函数大大改善了这种情况。 If your class X has a move constructor (which will look like X x(X&& m) { ... } , then you can change your statement to stlMap["test"] = std::move(x); . That statement is essentially equivalent to constructing a single X and then moving it to ownership of the map. Look up some articles on C++0x move semantics if you're not clued up, it's useful stuff. 如果你的类X有一个移动构造函数(它看起来像X x(X&& m) { ... } ,那么你可以将你的语句改为stlMap["test"] = std::move(x);那个语句本质上相当于构造一个X然后将其移动到地图的所有权。如果你没有搞清楚,那么查看一些关于C ++ 0x移动语义的文章,它是有用的东西。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM