c++11总结24——emplace_back

问题引入

拿std::deque的push_back举例,其源码如下:

public: // push_* and pop_*
    void push_back(const value_type& t) {
        if (finish.cur != finish.last - 1){
            // 最后缓冲区尚有一个以上的备用空间
            construct(finish.cur, t); //直接在备用空间上构造元素
            ++finish.cur; //调整最后缓冲区的使用状态
        }
        else //最后缓冲区已无(或只剩一个)元素备用空间
            push_back_aux(t);
}

construct函数的源码如下:

template
inline void construct(T1* p, const T2& value) {
	new(p)T1(value);
}

这里只探讨元素push_back进容器之后发生了什么事情,主要有三个步骤:

1)调用构造函数,构造临时对象;

2)调用拷贝构造函数,将临时对象放入容器中;

3)调用析构函数,销毁临时变量;

这个过程会造成临时变量申请资源的浪费。

emplace_back

c++11中引入了emplace_back,源码如下:

template 
decltype(auto) emplace_back(_Valty&&... _Val)   //右值引用
{	
    // insert by perfectly forwarding into element at end, provide strong guarantee
	if (_Has_unused_capacity())
	{
		return (_Emplace_back_with_unused_capacity(_STD forward<_Valty>(_Val)...));
	}
    //在调用重新构造时,将参数再完美转发出去
	_Ty& _Result = *_Emplace_reallocate(this->_Mylast(), _STD forward<_Valty>(_Val)...);
#if _HAS_CXX17
	return (_Result);
#else /* ^^^ _HAS_CXX17 ^^^ // vvv !_HAS_CXX17 vvv */
	(void)_Result;
#endif /* _HAS_CXX17 */
}

emplace_back使用了右值引用,调用了构造函数和移动构造函数,提升了效率。

关于右值引用,可以参考:c++11总结03——右值引用_却道天凉_好个秋的博客-CSDN博客

实例分析

void ThreadPool::start(int numThreads)
{
  assert(threads_.empty());
  running_ = true;
  threads_.reserve(numThreads);
  for (int i = 0; i < numThreads; ++i)
  {
    char id[32];
    snprintf(id, sizeof id, "%d", i+1);
    threads_.emplace_back(new muduo::Thread(
          std::bind(&ThreadPool::runInThread, this), name_+id));   //将thread的实例放入threads容器中 提高插入效率
    threads_[i]->start();
  }
  if (numThreads == 0 && threadInitCallback_)
  {
    threadInitCallback_();
  }
}

你可能感兴趣的:(c++11/17,c++)