c++ - C风格数组的标准容器

标签 c++ arrays std

有可变大小的 C 风格数组的 std 容器吗? 比如我有如下代码

int size = 5;    // This is not a constant in general
int *my_array = SpecialAllocationFunction(size);

我希望能够使用 C++ 标准样式容器访问此数组。具有迭代器和函数的东西,例如:sizebeginend、...

我知道我可以使用 std::array 如果 my_array 有一个常量大小。我自己也可以写一个,但我觉得一定要有现成的。

最佳答案

使用自定义分配器,可以构建一个大小仅在运行时已知的 vector (因此 std::array 不可能),包装现有数组。甚至可以通过覆盖特殊的 construct 方法(*) 来保留预先存在的值。

这是一个可能的实现:

/**
 * a pseudo allocator which receives in constructor an existing array
 *  of a known size, and will return it provided the required size
 *  is less than the declared one. If keep is true in contructor, 
 *  nothing is done at object construction time: original values are
 *  preserved
 * at deallocation time, nothing will happen
 */
template <class T>
class SpecialAllocator {
    T * addr;
    size_t sz;
    bool keep;
public:
    typedef T value_type;
    SpecialAllocator(T * addr, size_t sz, bool keep):
        addr(addr), sz(sz), keep(keep) {}
    size_t max_size() {
        return sz;
    }
    T* allocate(size_t n, const void* hint=0) {
        if (n > sz) throw std::bad_alloc();  // throws a bad_alloc... 
        return addr;
    }
    void deallocate(T* p, size_t n) {}
    template <class U, class... Args>
    void construct(U* p, Args&&... args) {
        if (! keep) {
            ::new((void *)p) U(std::forward<Args>(args)...);
        }
    }
    template <class U>
    void destroy(U* p) {
        if (! keep) {
            p->~U();   // do not destroy what we have not constructed...
        }
    }

};

然后可以这样使用:

int size = 5;    // This is not a constant in general
int *my_array = SpecialAllocationFunction(size);

SpecialAllocator<int> alloc(my_array, size);
std::vector<int, SpecialAllocator<int> > vec(size, alloc);

从那时起,vec 将是一个真正的 std::vector 包装 my_array

这里是一个简单的代码作为演示:

int main(){
    int arr[5] = { 5, 4, 3, 2, 1 };
    SpecialAllocator<int> alloc(arr, 5, true); // original values will be preserved
    std::vector<int, SpecialAllocator<int> > vec(5, alloc);
    for(auto it= vec.begin(); it != vec.end(); it++) {
        std::cout << *it << " ";
    }
    std::cout << std::endl;
    try {
        vec.push_back(8);
    }
    catch (std::bad_alloc& a) {
        std::cout << "allocation error" << std::endl;
    }
    return 0;
}

会成功输出:

5 4 3 2 1 
allocation error

(*) 注意构造/销毁可能涉及不同的地方:push_backemplace_back、等。在使用无操作 constructdestroy 方法之前,请仔细考虑您的实际用例。

关于c++ - C风格数组的标准容器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49450936/

相关文章:

c++ - 快速 1/X 除法(倒数)

php - 匹配 PHP 数组中的数据并显示不匹配的内容

ios - 从 JSON 数组创建变量

java - 从 2 个已知数组中初始化新数组

c - 如何使用 NO STDLIB/STDIO 函数将 unsigned long long 转换为字符串

c++ - `std::vector<T>::clear` *真的*没有指定时间复杂度吗?

c++ - 如何解决似乎不太可能是内存不足问题的 bad_alloc?

c++ - 如何在 C++ 中读取字符串中以空格分隔的多个 double ?

C++ 继承、模板和覆盖

c++ - 确定 std::string 是否具有所有唯一字符 [C++]