0

데이터를 연속 메모리 블록에 저장하고 차원 중 하나에서 동적 인 C++ 다차원 저장소 개체를 찾고 있습니다. 이 접근 방법을 권할 수 있습니까?반 동적 다차원 저장 개체

예 :

std::vector<std::array<int, 250>> pixelsMarker; 
// The array stores its data in a continuous block 
// but the vector data not continuous, because 
// an std::array is a complex object 

std::vector<int[250]> pixelsMarker 
// This is an invalid definition of a vector 
+0

벡터 데이터는 항상 연속입니다. – amchacon

+0

@amchacon 벡터가 연속이라는 것을 알게되지만 std :: array를 저장하면 std :: array 클래스 래퍼도 저장되므로 전체 데이터가 연속적이지는 않습니다. –

+0

'std :: array'에 대한 클래스 래퍼는 실질적으로 아무것도 없거나'std :: array >'연속하지 않을 것입니다. – user4581301

답변

1

여기 행수가 semi_dynamic_matrix::insert_row, semi_dynamic_matrix::erase_row, semi_dynamic_matrix::pop_rowsemi_dynamic_matrix::rows_resize하여 실행 시간에 변경 될 수있는 로우 - 주요 구성 하부 컨테이너 유형으로 std::vector를 사용하여 구현 가능하다. 이 클래스에 대한 작업을 전형적인 <algorithm> 헤더 (등)을 수행 할 수 있습니다 있도록

template<typename Ty, 
    class Allocator = std::allocator<Ty> 
> class semi_dynamic_matrix { 
    class proxy_row_vector { // use to allow [][] usage on semi_dynamic_matrix objects 
    public: 
     proxy_row_vector(std::vector<Ty, Allocator>& _vec, std::size_t i, std::size_t cols) 
      : vec(_vec), row_ind(i), cols_(cols) {} 
     const Ty& operator[](std::size_t j) const { 
      return vec[row_ind*cols+j]; 
     } 
     Ty& operator[](std::size_t j) { 
      return vec[row_ind*cols+j]; 
     } 
    private: 
     std::vector<Ty, Allocator>& vec; 
     std::size_t row_ind; 
     std::size_t cols_; 
    }; 
public: 
    // PUBLIC TYPEDEFS 
    typedef Ty value_type; 
    typedef Ty& reference; 
    typedef const Ty& const_reference; 
    typedef Ty* pointer; 
    typedef const Ty* const_pointer; 
    typedef std::size_t size_type; 
    typedef std::ptrdiff_t difference_type; 
    typedef Allocator allocator_type; 
    typedef typename std::vector<Ty,Allocator>::iterator iterator; 
    // and similar for const_iterator, reverse_iterator... 
    // CONSTRUCTION/ASSIGNMENT 
    // default constructor 
    semi_dynamic_matrix() : semi_dynamic_matrix(Allocator()) {} 
    explicit semi_dynamic_matrix(const Allocator& alloc) 
     : mtx(alloc), rows_(0U), cols_(0U) {} 
    // construct matrix of size rows*cols 
    explicit semi_dynamic_matrix(size_type rows, size_type cols, const Allocator& alloc = Allocator()) 
     : mtx(rows*cols, alloc), rows_(rows), cols_(cols) {} 
    // other constructors (copy, move, ...) 
    // CAPACITY 
    size_type rows() const noexcept { return rows_; } 
    constexpr size_type columns() const noexcept { return cols_; } 
    // ELEMENT ACCESS 
    proxy_row_vector operator[](size_type i) const { 
     return proxy_row_vector(mtx, i, cols_); 
    } 
    proxy_row_vector operator[](size_type i) { 
     return proxy_row_vector(mtx, i, cols_); 
    } 
    // other accessors, e.g. at(), front(), ... 
    // ITERATORS 
    iterator begin() noexcept { return mtx.begin(); } 
    iterator end() noexcept { return mtx.end(); } 
    // similarly for cbegin(), cend(), rbegin(), ... 
    // MODIFIERS 
    iterator insert_row(size_type row_pos, const value_type& val) { 
     return insert_row(row_pos, std::vector<value_type>(cols_, val)); 
    } 
    iterator insert_row(size_type row_pos, const std::vector<value_type>& row_vec) { 
     if (row_pos > rows_) throw std::out_of_range("message"); 
     if (row_vec.size() != cols_) throw std::invalid_argument("message"); 
     ++rows_; 
     return mtx.insert(mtx.begin()+row_pos*cols_, row_vec.begin(), row_vec.end()); 
    } 
    iterator insert_row(size_type row_pos, std::vector<value_type>&& row_vec = 
     std::vector<value_type>()) { 
     if (row_pos > rows_) throw std::out_of_range("message"); 
     if (row_vec.size() > cols_) throw std::invalid_argument("message"); 
     ++rows_; 
     if (row_vec.size() < cols_) row_vec.resize(cols_); 
     return mtx.insert(mtx.begin()+row_pos*cols_, std::make_move_iterator(
      row_vec.begin()), std::make_move_iterator(row_vec.end())); 
    } 
    iterator erase_row(size_type row_pos) { 
     if (!(row_pos < rows_)) throw std::out_of_range(""); 
     --rows_; 
     return mtx.erase(mtx.begin()+row_pos*cols_, mtx.begin()+cols_*(row_pos+1)); 
    } 
    void pop_row() { 
     for (size_type i = 0; i < cols_; ++i) mtx.pop_back(); 
     --rows_; 
    } 
    void rows_resize(size_type rows) { 
     size_type tmp_rows = rows_; 
     if (rows == rows_) return; 
     if (rows > rows_) { // expand 
      for (size_type i = 0; i < (rows_-tmp_rows); ++i) 
       insert_row(rows_, std::move(std::vector<value_type>(cols_))); 
     } 
     else { // contract 
      for (size_type i = 0; i < (tmp_rows-rows); ++i) pop_row(); 
     } 
    } 
private: 
    std::vector<value_type, allocator_type> mtx; 
    size_type rows_; 
    size_type cols_; 
}; 

은 그럼 당신은

semi_dynamic_matrix<int> sdm(3,3); // create matrix of size 3x3 
sdm.rows_resize(5); // resize matrix to 5x3 
sdm.erase_row(0); // erase first row of matrix, size is now 4x3 

가 기본이 반복자 타입 그냥 std::vector 반복자를 사용하므로 같은이를 사용할 수 있습니다.

또는 행과 열 모두에서 동적 인 행렬 구조를 원한다면 잠시 전에 작성한 구현을 사용해보십시오 (dynamic_matrix).

2

왜 당신은 데이터에 직접 접근을 생성하지 않으며 단지 하나의 배열을 사용합니까? 예를 들어

은 : 여기

std::vector<int> myArray(250*100); 

경우 (250 * 100 크기의 단일 배열) (250)의 크기가 각각 100 개 개의 배열을 만든다. 배열 N의 요소에 액세스하려면, 함수

int accessor(int N, int elementNum) 
{ 
    return N*250 + elementNum; 
} 

를 사용하여이 배열 번째 N '당신에게 요소 elementNum을 줄 것이다.

물론 언제든지 std::vector에서 상속하거나이 작업을 수행 할 자신 만의 클래스를 만들 수 있습니다.

+0

나는 수정할 수없고 연속적인 데이터 블록에서만 작동한다. –

+0

@ AdamHunyadi 내가 제안한 해결책에서 계속되지 않는 것은 무엇입니까? –

+1

@TheQuantumPhysicist 절대적으로 아무것도 아니지만 OP의 원래 std :: vector > 기반 기반 솔루션은 여전히 ​​연속적이었습니다. 여전히 문제는 보이지 않습니다. 사실 받아 들인 솔루션은 당신이했던 것과 똑같은 일을하지만 접근 자 함수 대신 객체로 래핑합니다. – user4581301

1

N 차원 std::array을 연속 블록으로 만들려면 std::array에 추가 오버 헤드가 없어야합니다. std::array에 있어야하는 유일한 데이터는 배열입니다. 배열에 관한 모든 데이터는 템플릿에 의해 고정됩니다.

그래서

std::array<std::array<int, 250>, 100> data; 

가 연속 인 경우 다음

std::vector<std::array<int, 250>> data; 

은 연속 될 것입니다.

즉, 최근에 무료로 구할 수있는 표준 초안 (공식 사본이 없음)에서 구현이 다른 구성원이나 다른 구성원을 추가 할 수 없다는 것을 보장 할 수는 없습니다. 모두를 위해 그것을 망칠뿐입니다.하지만 왜 그런 일을합니까?