有没有办法将已经初始化的数据移动到 a 中std::vector?
这是我自己的简单vec课程:
template<typename T>
class vec final
{
std::unique_ptr<T[]> pValues;
size_t size = 0;
public:
std::span<T> span() const { return std::span<int>(pValues.get(), size); }
vec(T* p, size_t sz) : size(sz) { pValues.reset(p); }
};
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,它将获得传递给它的内存的所有权:
int main()
{
constexpr size_t count = 99;
auto orig = std::make_unique<int[]>(count);
{
std::span<int> orig_(orig.get(), count);
std::iota(orig_.begin(), orig_.end(), -1);
assert((orig_[0] == -1) && (orig_[1] == 0) && (orig_[98] == 97));
}
vec<int> nums(orig.release(), count);
auto nums_ = nums.span();
assert((nums_[0] == -1) && (nums_[1] == 0) && (nums_[98] == 97));
}
Run Code Online (Sandbox Code Playgroud)
这一切都“按需要”工作,但我想做类似的事情std::vector;特别是,我不想将数据复制到 a std::vector(想象一下count明显大于99)。
换句话说,我想做“围绕一些指针进行复制”(通常)当我从std::move一个指针std::vector指向另一个指针时发生;但来源是我自己的指针。正如我的示例代码所示,这很“容易”,但我不想要我自己的vec.
当我完成后,我想“交通”,因为std::vector这样我就可以完全忘记内存管理(并进一步扩展我自己的vec类)。使用 astd::vector也适用于无法更改的现有 C++ 代码。
您可以通过为 std::vector 提供自定义分配器来使用已分配的内存:
#include <limits>
#include <iostream>
#include <memory>
#include <vector>
#include <numeric>
#include <cassert>
// allocator adapter to use pre-allocated memory
template <typename T, typename A=std::allocator<T>>
class reuse_mem_allocator : public A {
typedef std::allocator_traits<A> a_t;
public:
typedef typename a_t::size_type size_type;
typedef typename a_t::pointer pointer;
template <typename U> struct rebind {
using other =
reuse_mem_allocator<
U, typename a_t::template rebind_alloc<U>
>;
};
// have to store a ptr to pre-allocated memory and num of elements
reuse_mem_allocator(T* p = nullptr, size_type n = 0) throw()
: p_(p)
, size_(n)
{ }
reuse_mem_allocator(const reuse_mem_allocator& rhs) throw()
: p_(rhs.p_)
, size_(rhs.size_)
{ }
// allocate but don't initialize num elements of type T
pointer allocate (size_type num, const void* = 0) {
// Unless, it is the first call, and
// it was constructed with pre-allocated memory.
if (size_ != 0) {
if (num == size_) {
// Then, don't allocate; return pre-allocated mem
size_ = 0; // but only once
return p_;
} else {
throw std::bad_alloc();
}
} else {
// allocate memory with global new
T* ret = (T*)(::operator new(num*sizeof(T)));
return ret;
}
}
// convert value initialization into default/new initialization
template <typename U>
void construct(U* ptr)
noexcept(std::is_nothrow_default_constructible<U>::value) {
::new(static_cast<void*>(ptr)) U;
}
template <typename U, typename...Args>
void construct(U* ptr, Args&&... args) {
a_t::construct(static_cast<A&>(*this),
ptr, std::forward<Args>(args)...);
}
private:
pointer p_;
size_type size_;
};
int main()
{
constexpr size_t count = 9;
auto orig = std::make_unique<int[]>(count);
std::iota(orig.get(), orig.get()+count, -1);
assert((orig[0] == -1) && (orig[1] == 0) && (orig[count-1] == count-2));
std::vector<int, reuse_mem_allocator<int>> num(count, reuse_mem_allocator(orig.release(), count));
for (auto e : num) {
std::cout << e << " ";
}
std::cout << "\n";
std::cout << "size: " << num.size() << "\n";
}
Run Code Online (Sandbox Code Playgroud)
我用c++17编译的。这是输出:
-1 0 1 2 3 4 5 6 7
size: 9
Run Code Online (Sandbox Code Playgroud)
分配器适配器基于此答案中的分配器适配器。
| 归档时间: |
|
| 查看次数: |
1005 次 |
| 最近记录: |