C++ 浅谈emplace_back及误区

来源:互联网 发布:foreach去除数组重复值 编辑:程序博客网 时间:2024/06/15 03:28

今天做c++ primer题目实现标准库vector,emplace_back忽然发现我对其了解甚少,首先,我在网上找到答案的代码,之前有过了解emplace_back是通过移动构造函数实现的,那么问题来了,如果我想实现vector<Base> b这样,我将其移动构造函数显式删除,那么

b.emplace_back(....),还能工作吗? 答案是 : 能

//Base.h
#include<string>
class Base
{
public:
Base() = default;
Base(std::string t,int m):s(t),i(m){}
Base(const Base& b):s(b.s),i(b.i){}
Base(Base&&) = delete;
private:
std::string s;
int i;
};

这似乎符合我们的期望,可当我尝试使用自定义的版本(也就是网上那些"高手"的,还是外国人放在github的,呵呵啦,害我找这么久原因,不是坑吗?)自定义版本如下:

template<typename T>
template<class ...Args>
void
Vec<T>::emplace_back(Args&& ...args)
{
chk_n_alloc();
alloc.construct(first_free++, std::forward<Args>(args)...);
}

chk_n_alloc是安全检查的(其实坑就在这“里”),好下面贴chk_n_alloc代码

void chk_n_alloc() { if (size() == capacity()) reallocate(); }

好又有个reallocate(),那再看看它吧:

void Vec<T>::reallocate()
{
std::size_t newcap = size() ? 2 * size() : 1;
wy_alloc_n_move(newcap);
}

又有个wy_alloc_n_move(),看这名字离坑应该不远了:

template<typename T>
void inline Vec<T>::wy_alloc_n_move(size_t n)
{
std::size_t newcap = n;
T* newdata = alloc.allocate(n);
T* dest = newdata;
T* old = elements;
for (size_t i = 0; i != size(); ++i)
alloc.construct(dest++,std::move(*(old++)));
free();
elements = newdata;
first_free = dest;
cap = newcap + elements;
}

好吧,我们到达坑了,看到std::move(*(old++))我既高兴又愤怒,(其实找不到恐怕我要砸电脑了)*old是Base类型的,而我delete这个函数,当然不行了,把move弄掉就能运行成功,可是这不符合设计理念,标准库太复杂,我也无迹可寻(所以不是什么人都可以写标准库的,待我学有所成再补充实现标准库里怎么delete移动构造函数也能用的,当然也欢迎各位大佬补充。(要这个有缺陷源码的也可以q我 邮箱:577482975@qq.com)

1 0
原创粉丝点击