首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >std::vector emplace_back实现

std::vector emplace_back实现
EN

Stack Overflow用户
提问于 2021-06-09 17:08:52
回答 2查看 395关注 0票数 0

我实现的push_back函数:

代码语言:javascript
复制
void push_back(T& num) {
    my_vec[index] = num;
    index++;
}

和emplace_back函数:

代码语言:javascript
复制
template<class... Args>
void emplace_back(Args&&... args) {
    push_back(T(std::forward<Args>(args)...));
}

你觉得这有什么问题吗?如果是,你能告诉我吗?

另外,请让我知道这是如何工作的?

请注意: emplace_back不是我的实现,我是在寻找实现我自己的emplace_back的方法时从其他问题中获取的。

EN

回答 2

Stack Overflow用户

发布于 2021-06-09 18:55:59

你并不是真的在使用它。还有一项任务。

它使用T数组的大小和对齐来分配原始内存,然后实例化原始内存中的对象。

考虑到这一点,您可能应该用emplace_back来实现push_back,而不是相反。

代码语言:javascript
复制
template <typename T>
class my_vector {
    T * start;
    std::size_t size;
    std::size_t capacity;

    void grow(); // Implementation of this is left as an exercise to the reader

public:
    template <typename... Args>
    reference emplace_back(Args&&... args) {
        if (size == capacity) grow();
        return *new (start + size++) T(std::forward<Args>(args)...);
    }

    reference push_back(const T & t) { return emplace_back(t); }
    reference push_back(T && t) { return emplace_back(std::move(t)); }
}

还有,请让我知道这是如何工作的?

template <typename... Args>允许零个或多个类型匹配此模板,然后T(std::forward<Args>(args)...)使用这些参数构造一个T"perfectly forwarding",即,右值作为右值传递,左值作为左值传递。

注:因为std::vectornew[],所以您不能实现行为与std::vector 20之前的C++完全相同的东西,因为它必须能够在不构造T数组的情况下从data返回指向T数组的指针。

票数 2
EN

Stack Overflow用户

发布于 2021-06-09 18:50:41

emplace_back的要点是在适当的位置构造一个对象。您的实现构造了一个对象,然后将其复制到my_vec

您的实现将无法处理不可复制的类型。例如,这将不会编译:

代码语言:javascript
复制
Vector<std::thread> v;
v.emplace_back([](){});
v.push_back(std::thread([](){}));

push_back更改为通过右值引用接受其参数将解决此问题:

代码语言:javascript
复制
void push_back(T&& num) {
    my_vec[index] = std::move(num);
    index++;
}

template<class... Args>
void emplace_back(Args&&... args) {
    push_back(T(std::forward<Args>(args)...));
}

然而,我认为大多数标准库实现都是使用emplace_back作为最低层函数来实现的:

代码语言:javascript
复制
void push_back(T&& num) {
    emplace_back(std::move(num));
}

template<class... Args>
void emplace_back(Args&&... args) {
    my_vec[index] = T(std::forward<Args>(args)...);
    index++;
}

这使得实现复制值的push_back重载变得更容易:

代码语言:javascript
复制
void push_back(const T& num) {
    emplace_back(num);
}

注意,这个实现使用了移动赋值,这仍然不是emplace_back的意图,它需要在未初始化的内存上使用位置新构造一个对象,但假设my_vec是一个对象数组或类似的对象,这是您所能做的最好的事情(没有完全实现std::vector的语义,这是相当复杂的)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67900997

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档