动态分配矢量(或矢量矢量)

时间:2011-07-21 11:58:22

标签: c++ vector

我需要动态分配大小在运行时给出的1-D和2-D数组。

我设法“发现”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));

9 个答案:

答案 0 :(得分:50)

如您所发现的那样,在运行时给出维度时,需要动态分配数组。

但是,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));

答案 1 :(得分:9)

您将两个问题混为一谈,即动态分配和可调整大小的容器。你不需要担心动态分配,因为你的容器已经为你做了,所以就这样说:

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

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

答案 2 :(得分:4)

你正在做什么应该基本上工作,然而

通常,不会动态分配对象

如果你想要一个矢量,请执行以下操作:

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

不是这个:

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

后者为您提供了一个必须删除的指针。前者为你提供了一个向量,当它超出范围时,它会自行清理。 (当然,它在内部动态分配对象,但诀窍在于它由类本身处理,您无需在用户代码中担心它。)

答案 3 :(得分:2)

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

您可以使用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_;
};

答案 4 :(得分:2)

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

答案 5 :(得分:1)

您不会动态分配容器。如果他们自己不是手动管理的,他们可以自动管理内存。

当您使用push_back(或insert)添加新项目时,向量会增长,您可以从一开始就使用构造函数的参数选择其大小,然后您可以使用{{ 1}}方法。

使用构造函数创建带有大小的向量向量,如下所示:

resize

这意味着:std::vector< std::vector<double> > matrix(size, std::vector<double>(sizeY)); size个实例,每个std::vector<double>个实例包含sizeY两倍(初始化为0.0)。

答案 6 :(得分: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;
}

答案 7 :(得分: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;

     }

答案 8 :(得分:-1)

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

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

#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));

从本质上讲,我所做的就是删除一个括号(()。