半动态多维存储对象
Half-dynamic multidimensional storage object
我正在寻找一个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
为什么不创建自己的数据访问器并使用单个数组呢?
例如:std::vector<int> myArray(250*100);
这里创建了100个数组,每个数组的大小为250(这是一个大小为250*100的数组)。要访问数组N
中的元素,可以使用函数
int accessor(int N, int elementNum)
{
return N*250 + elementNum;
}
这将给你N
'th数组中的元素elementNum
。
当然,您总是可以选择从std::vector
继承或创建您自己的类来为您做这些。
这是一个可能的实现,在行为主配置中使用std::vector
作为底层容器类型,其中可以在运行时使用semi_dynamic_matrix::insert_row
, semi_dynamic_matrix::erase_row
, semi_dynamic_matrix::pop_row
和semi_dynamic_matrix::rows_resize
更改行数。
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
迭代器,因此您可以在该类上执行任何典型的<algorithm>
头(和其他)操作。
或者,如果你想要一个行和列都是动态的矩阵结构,那么考虑使用我之前创建的实现:dynamic_matrix
.
为了使n维std::array
成为连续块,std::array
必须没有额外的开销。唯一应该在std::array
中的数据是数组。关于数组的所有数据都由模板固定。
所以如果
std::array<std::array<int, 250>, 100> data;
是连续的,那么
std::vector<std::array<int, 250>> data;
也将是连续的
也就是说,我找不到(或解释)任何在最近的免费的标准草案(没有正式的副本),以保证一个实现不会添加一个或两个成员,只是为了破坏它的每个人,但为什么要这样做呢?
- 如何使用 stl 容器有效地存储对象?(即根据其字段的值进行搜索)
- 线程上下文上的静态存储对象优化
- OOP - 存储对象和服务接口
- 为什么存储对象地址在缓冲区中会导致内存泄漏并删除它们
- 是否保证在销毁所有线程本地存储对象后销毁全局对象
- 使用列表存储对象
- 在c++中存储一个对象或不存储对象的首选方式是什么
- 更好的是:存储对象与存储指针
- 应用程序使用QMAP存储对象时停止响应
- 使用堆栈存储对象
- 如何在 std::map 中存储"对象类型"?
- 我应该如何存储对象
- 在 c++ 中存储对象的最佳策略是什么,确保名称唯一并能够在以后有效地检索它们
- 用于存储对象列表的最佳标准类
- 在C++中存储对象地址的数据结构
- 函子如何维护/存储对象的状态
- 我如何定义一个向量,并用C++在其中存储对象
- 存储对象以备将来使用(在重新启动程序时)
- C++/JNI-存储对象(jobject)在向量和数组中发生意外更改,C++或JNI问题
- 在多个容器中存储对象的最佳实践