动态分配向量(或向量的向量)

allocating vectors (or vectors of vectors) dynamically

本文关键字:向量 动态分配      更新时间:2023-10-16

我需要动态分配一维和二维数组,它们的大小在运行时给定。

我设法"发现"了std::vector,我认为它符合我的目的,但我想问一下我所写的是否正确和/或可以改进。

这就是我正在做的:

#include <vector>
typedef std::vector< std::vector<double> > matrix;
//... various code and other stuff
std::vector<double> *name = new std::vector<double> (size);
matrix *name2 = new matrix(sizeX, std::vector<double>(sizeY));

正如您所发现的,当您的维度在运行时给定时,需要动态分配数组。

然而,std::vector已经是这个过程的包装器,所以动态分配向量就像一个双正数。这是多余的。

写(c++ 98):

#include <vector>
typedef std::vector< std::vector<double> > matrix;
matrix name(sizeX, std::vector<double>(sizeY));

或(c++ 11及更新版本):

#include <vector>
using matrix = std::vector<std::vector<double>>;
matrix name(sizeX, std::vector<double>(sizeY));

您正在合并两个问题,动态分配和可调整大小的容器。您不需要担心动态分配,因为您的容器已经为您做了,所以只需这样说:

matrix name(sizeX, std::vector<double>(sizeY));

这将使name成为一个具有自动存储持续时间的对象,并且您可以通过name[i][j]访问它的成员。

你所做的应该基本有效,然而:

通常,不动态分配对象

如果你想要一个向量,这样做:

std::vector<double> vec(size);

不是这样的:

std::vector<double>* vec = new std::vector<double>(size);

给你一个指针,你必须删除它。前者给你一个向量,当它超出作用域时,它会自我清理。(当然,在内部,它动态地分配对象,但诀窍是这是由类本身处理的,您不需要在用户代码中担心它)。

这是正确的,但可以提高效率。

你可以使用boost多维数组:http://www.boost.org/doc/libs/1_47_0/libs/multi_array/doc/user.html

或者,您可以为它实现自己的类并自己处理索引。也许是这样的(没有经过很好的测试):

#include <vector>
#include <cassert>
template <typename T, typename A = std::allocator<T> >
class Array2d
{
public:
    typedef Array2d<T> self;
    typedef std::vector<T, A> Storage;
    typedef typename Storage::iterator       iterator;
    typedef typename Storage::const_iterator const_iterator;
    Array2d() : major_(0), minor_(0) {}
    Array2d(size_t major, size_t minor)
        : major_(major)
        , minor_(minor)
        , storage_(major * minor)
    {}
    template <typename U>
    Array2d(size_t major, size_t minor, U const& init)
        : major_(major)
        , minor_(minor)
        , storage_(major * minor, u)
    {
    }
    iterator begin()                { return storage_.begin(); }
    const_iterator begin() const    { return storage_.begin(); }
    iterator end()                  { return storage_.end(); }
    const_iterator end() const      { return storage_.end(); }
    iterator begin(size_t major) {
        assert(major < major_);
        return storage_.begin() + (major * minor_);
    }
    const_iterator begin(size_t major) const {
        assert(major < major_);
        return storage_.begin() + (major * minor_);
    }
    iterator end(size_t major) {
        assert(major < major_);
        return storage_.begin() + ((major + 1) * minor_);
    }
    const_iterator end(size_t major) const {
        assert(major < major_);
        return storage_.begin() + ((major + 1) * minor_);
    }
    void clear() {
        storage_.clear();
        major_ = 0;
        minor_ = 0;
    }
    void clearResize(size_t major, size_t minor)
    {
        clear();
        storage_.resize(major * minor);
        major_ = major;
        minor_ = minor;
    }
    void resize(size_t major, size_t minor)
    {
        if ((major != major_) && (minor != minor_))
        {
            Array2d tmp(major, minor);
            swap(tmp);
            // Get minimum minor axis
            size_t const dist = (tmp.minor_ < minor_) ? tmp.minor_ : minor_;
            size_t m = 0;
            // copy values across
            for (; (m < tmp.major_) && (m < major_); ++m) {
                std::copy(tmp.begin(m), tmp.begin(m) + dist, begin(m));
            }
        }
    }
    void swap(self& other)
    {
        storage_.swap(other.storage_);
        std::swap(major_, other.major_);
        std::swap(minor_, other.minor_);
    }
    size_t minor() const {
        return minor_;
    }
    size_t major() const {
        return major_;
    }
    T*       buffer()       { return &storage_[0]; }
    T const* buffer() const { return &storage_[0]; }
    bool empty() const {
        return storage_.empty();
    }
    template <typename ArrRef, typename Ref>
    class MajorProxy
    {
        ArrRef arr_;
        size_t major_;
    public:
        MajorProxy(ArrRef arr, size_t major)
        : arr_(arr)
        , major_(major)
        {}
        Ref operator[](size_t index) const {
            assert(index < arr_.minor());
            return *(arr_.buffer() + (index + (major_ * arr_.minor())));
        }
    };
    MajorProxy<self&, T&>
    operator[](size_t major) {
        return MajorProxy<self&, T&>(*this, major);
    }
    MajorProxy<self const&, T const&>
    operator[](size_t major) const {
        return MajorProxy<self&, T&>(*this, major);
    }
private:
    size_t major_;
    size_t minor_;
    Storage storage_;
};

虽然其他答案的要点非常正确(不要通过new动态分配向量,而是让向量进行分配),但如果您正在考虑向量和矩阵(例如线性代数),您可能要考虑使用Eigen矩阵库。

不能动态分配容器。如果它们本身不是手动管理的,它们可以自动为您管理内存。

当您使用push_back(或insert)添加新项时,vector会增长,您可以从构造函数的参数开始选择它的大小,然后可以使用resize方法调整它的大小。

用构造函数创建一个具有大小的vector的vector:

std::vector< std::vector<double> > matrix(size, std::vector<double>(sizeY));

这意味着:std::vector<double>size个实例,每个实例包含sizeY双精度(初始化为0.0)。

有时您不想填充堆栈,并且您的内存需求很大。因此,您可能希望使用vector>动态创建,特别是在创建给定行和col值的表时。

这是我在c++ 11中的看法

int main() {
    int row, col;
    std::cin >> row >> col;
    auto *arr = new std::vector<std::vector<int>*>(row);
    for (int i=0; i<row; i++) {
        auto *x = new std::vector<int>(col, 5);
        (*arr)[i] = x;
    }
    for (int i=0; i<row; i++) {
        for(int j=0; j<col; j++) {
            std::cout << arr->at(i)->at(j) << " ";
        }
        std::cout << std::endl;
    }
    return 0;
}
 #include < iostream > 
 #include < vector >
 using namespace std;
int main(){
vector<int>*v = new vector<int>();   // for 1d vector just copy paste  it
v->push_back(5);
v->push_back(10);
v->push_back(20);
v->push_back(25);
for(int i=0;i<v->size();i++){
    cout<<v->at(i)<<" ";
}
cout<<endl;
delete v;
system("pause");
return 0;
     }

如果您不需要在运行时调整数组大小,那么您可以使用标准数组(在运行时分配)!

但是,如果你确实需要在运行时调整数组的大小,那么你可以使用以下(修改过的)代码:

#include <vector>
typedef std::vector< std::vector<double> > matrix;
//... various code and other stuff
std::vector<double> *name = new std::vector<double> (size);
matrix *name2 = new matrix(sizeX, std::vector<double>(sizeY));

实际上,我所做的只是删除了一个括号(()。