2011-07-21 68 views
14

我需要動態分配一維和二維數組,其大小在運行時給出。動態分配向量(或向量向量)

我設法「發現」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)); 

回答

45

正如您發現的那樣,在運行時給出維度時,需要動態分配數組。

但是,std::vector已經是包裝圍繞這個過程,所以動態分配向量就像是雙重積極的。這是多餘的。

只要寫:

#include <vector> 

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

謝謝,真的很清楚,很有幫助。 :) – Federico

+0

@Federico:沒問題:) –

+1

我認爲這是我找到的最好的描述!也解決了我的問題。 – skr

7

你混爲一談兩個問題,動態分配和調整大小的容器。您不必擔心動態分配的,因爲你的容器會替你們,所以才說這樣的:

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

這將使name具有自動存儲時間的對象,就可以訪問它會員通過name[i][j]

+0

首先:感謝您的回覆。 然後,爲了完全確定我理解你的答案,你的意思是我不需要「新」與? – Federico

+0

簡短回答:的確,你沒有。中等答案:如果你習慣使用C++,反正你永遠不應該說'新'(可能的例外是'unique_ptr'的構造函數)。 –

+0

好吧,中等答案對我來說越來越難,你能給我一個參考嗎? 只是爲了理解你的意思是「地道」,或爲什麼我不應該使用'新' – Federico

3

你在做什麼應該基本工作,但

一般來說,不動態如果你想有一個分配對象

向量,執行此操作:

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

不是這個:

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

後者給你一個指針,你必須刪除。前者給你一個向量,當它超出範圍時,它會自行清理。 (當然,它在內部動態分配對象,但訣竅是這是由類本身處理的,並且不需要在用戶代碼中擔心)。

+0

如果您正在運行單線程應用程序,當然。多線程在內存分配方面引入了一整套新的和不可能的內容。 – pg1989

+0

@ pg1989:你是否建議在多線程應用程序中,你應該嘗試讓不同的線程執行分配和釋放?不,在多線程程序中,適用相同的規則,*只有更多*。 – jalf

+0

不,我更多的是指共享資源的併發訪問。也許我沒有說得對。確實,在慣用的C++中,你絕不應該明確地調用new。然而,你仍然需要考慮你所操作的對象,因爲如果一個線程試圖訪問一個已經被銷燬的對象,就會發生不好的事情。 – pg1989

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

從本質上講,所有我所做的就是刪除單個支架(( )。

+0

是的,這個筆記本電腦是一個錯字,我從原來的帖子中刪除它:P – Federico

+0

您的代碼應該是完全功能的! – foxy

1

您不會動態分配容器。如果他們本身不是手動管理的,他們可以自動管理內存。

載體的情況下添加新項目與push_back(或insert),你可以選擇從一開始就帶有參數的構造函數它的大小,你可以用resize方法後調整它的增長。

創建矢量與尺寸與構造的載體是這樣的:

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

這意味着:一個std::vector<double>size實例,每個包含sizeY雙打(初始化爲0.0)。

2

這是正確的,但可以提高效率。

你可以使用升壓多維數組: 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_; 
}; 
2

而其他的答案提出的觀點是非常正確的(不通過新的動態分配的載體,而是讓向量做分配) ,如果你正在考慮向量和矩陣的條件(如線性代數),你可能要考慮使用特徵矩陣庫。