C++ STL container and in-place construction

耗尽温柔 提交于 2020-01-01 09:27:30

问题


Please consider the following:

class CMyClass
{
public:
  CMyClass()
  {
    printf( "Constructor\n" );
  }
  CMyClass( const CMyClass& )
  {
    printf( "Copy constructor\n" );
  }
};

int main()
{
  std::list<CMyClass> listMyClass;

  listMyClass.resize( 1 );

  return 0;
}

It produces the following output:

Constructor

Copy constructor

Now my question is: How do I avoid the copy constructor? Or to put it in another way: How can I create objects inside an STL container without the unnecessary copy operation. Is there some way to do an "in-place" construction using the default constructor?


Update - answers so far:

  1. It can't be done
  2. Use pointers or smart pointers instead.

Smart pointers are an overkill for my application. But I really wonder why this can't be done. It seems like such an obvious thing to want to do. Any other ideas? I will even accept a nasty hack if it works...


Solution

I think I just found a solution for my problem from all the comments and answers posed here. The solution is to construct an empty object and to keep it around for the sole purpose of using it later for making clean copies of. Then you can use one of the methods that take a reference (like push_back or insert). This still calls the copy constructor for every new object inserted, but at least it is not both the default constructor AND copy constructor:

int main()
{
  CMyClass Empty;

  std::list<CMyClass> listMyClass;

  for ( int c=0; c<10; ++c )
  {
    listMyClass.push_back( Empty );
  }

  return 0;
}

回答1:


By design, all the C++ Standard Library containers store copies. Therefore the call to the copy constructor cannot be avoided if you wish to store values in the container - the only way out is to store pointers instead. If you want to mitigate the overhead of copying, investigate the use of reference counting.




回答2:


use pointers

std::list<CMyClass*> listMyClass;



回答3:


Sorry, not currently with std::list and similar containers. (But you can write your own slightly-different container if you really need this, and still follow the rest of the STL interface.)

You don't have to use the default ctor, however:

std::list<CMyClass> listMyClass;
listMyClass.resize(1, obj_to_copy_from);

Such as:

std::list<CMyClass> listMyClass;
listMyClass.resize(1, CMyClass(use, specific, ctor));

Resize looks like:

void list<T>::resize(size_type new_size, T copy_from = T());

Which creates a new object (using the default ctor) by default.




回答4:


It would be useful if vector allowed initializing new elements with default constructor on resize because of performance, but this is not supported. If you really need this, implement custom container - there is no other way.




回答5:


use a pointer or smart pointer (boost::shared_ptr and not auto_ptr)




回答6:


http://swagatata.tumblr.com/post/5896332725/vector-construction

Even if you do

std::list<classname> objectname(100);

the constructor would be called once and the 100 objects would be constructed using copy constructor.




回答7:


you can do in c11, for older versions, vesry simple can be improved

vector

myclas: public vector<A>
{
    push_back(Aconstructor_parameters)
    {
       new(_Mylast++) A(Aconstructor_parameters);
    }
};

when using ensure that you have used reserve() to allocate the memory



来源:https://stackoverflow.com/questions/2100239/c-stl-container-and-in-place-construction

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!