C ++ STL容器和就地构造

时间:2010-01-20 09:28:24

标签: c++ stl

请考虑以下事项:

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

它产生以下输出:

  

构造

     

复制构造函数

现在我的问题是:如何避免复制构造函数?或者换一种方式:如何在没有不必要的复制操作的情况下在STL容器内创建对象。有没有办法使用默认构造函数进行“就地”构造?


更新 - 到目前为止的答案:

  1. 无法完成
  2. 使用指针或智能指针 代替。
  3. 智能指针对我的应用程序来说太过分了。但我真的很想知道为什么不能这样做。这似乎是一件显而易见的事情。还有其他想法吗?如果有效,我甚至会接受讨厌的黑客......


    解决方案

    我想我刚从这里提出的所有评论和答案中找到了我的问题的解决方案。解决方案是构造一个空对象并将其保留,以便以后使用它来制作干净的副本。然后,您可以使用其中一个引用方法(如push_back或insert)。这仍然为每个插入的新对象调用复制构造函数,但至少它不是默认的构造函数和复制构造函数:

    int main()
    {
      CMyClass Empty;
    
      std::list<CMyClass> listMyClass;
    
      for ( int c=0; c<10; ++c )
      {
        listMyClass.push_back( Empty );
      }
    
      return 0;
    }
    

7 个答案:

答案 0 :(得分:8)

按照设计,所有C ++标准库容器都存储副本。因此,如果您希望将值存储在容器中,则无法避免对复制构造函数的调用 - 唯一的出路是存储指针。如果您想减轻复制的开销,请调查引用计数的使用。

答案 1 :(得分:1)

使用指针

std::list<CMyClass*> listMyClass;

答案 2 :(得分:1)

抱歉,目前没有使用std :: list和类似的容器。 (但是如果你真的需要它,你可以编写自己稍微不同的容器,并且仍然遵循STL接口的其余部分。)

但是,您不必使用默认的ctor:

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

如:

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

调整大小如下:

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

默认情况下会创建一个新对象(使用默认ctor)。

答案 3 :(得分:1)

如果vector因为性能而允许在resize上使用默认构造函数初始化新元素会很有用,但这不受支持。如果你真的需要这个,那就实现自定义容器 - 没有别的办法。

答案 4 :(得分:0)

使用指针或智能指针(boost :: shared_ptr而不是auto_ptr)

答案 5 :(得分:0)

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

即使你做了

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

构造函数将被调用一次,并且将使用复制构造函数构造100个对象。

答案 6 :(得分:0)

你可以在c11中做,对于旧版本,vesry simple可以改进

矢量

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

使用时确保您已使用reserve()分配内存