C++ 动态分配向量(或向量的向量)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6775643/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
allocating vectors (or vectors of vectors) dynamically
提问by Federico
I need to dynamically allocate 1-D and 2-D arrays whose sizes are given at run-time.
我需要动态分配大小在运行时给出的一维和二维数组。
I managed to "discover" std::vector
and I think it fits my purposes, but I would like to ask whether what I've written is correct and/or can be improved.
我设法“发现”std::vector
并且我认为它符合我的目的,但我想问一下我写的内容是否正确和/或可以改进。
This is what I'm doing:
这就是我正在做的:
#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));
回答by Lightness Races in Orbit
Dynamically allocating arrays is required when your dimensions are given at runtime, as you've discovered.
正如您所发现的,在运行时给定维度时,需要动态分配数组。
However, std::vector
is already a wrapperaround this process, so dynamically allocating vectors is like a double positive. It's redundant.
然而,std::vector
已经是这个过程的包装器,所以动态分配向量就像一个双重肯定。这是多余的。
Just write (C++98):
只需写(C++98):
#include <vector>
typedef std::vector< std::vector<double> > matrix;
matrix name(sizeX, std::vector<double>(sizeY));
or (C++11 and later):
或(C++11 及更高版本):
#include <vector>
using matrix = std::vector<std::vector<double>>;
matrix name(sizeX, std::vector<double>(sizeY));
回答by Kerrek SB
You're conflating two issues, dynamic allocation and resizable containers. You don't need to worry about dynamic allocation, since your container does that for you already, so just say it like this:
您将两个问题混为一谈,动态分配和可调整大小的容器。你不需要担心动态分配,因为你的容器已经为你做了,所以就这样说:
matrix name(sizeX, std::vector<double>(sizeY));
This will make name
an object with automatic storage duration, and you can access its members via name[i][j]
.
这将创建name
一个具有自动存储期限的对象,您可以通过name[i][j]
.
回答by jalf
What you're doing should basically work, however:
但是,您所做的基本上应该可以工作:
In general, don't dynamically allocate objects
一般来说,不要动态分配对象
If you want a vector, do this:
如果您想要一个向量,请执行以下操作:
std::vector<double> vec(size);
not this:
不是这个:
std::vector<double>* vec = new std::vector<double>(size);
The latter gives you a pointer, which you have to delete. The former gives you a vector which, when it goes out of scope, cleans up after itself. (Internally, of course, it dynamically allocates objects, but the trick is that this is handled by the class itself, and you don't need to worry about it in your user code).
后者为您提供了一个指针,您必须将其删除。前者为您提供了一个向量,当它超出范围时,它会自行清理。(当然,它在内部动态分配对象,但诀窍在于,这是由类本身处理的,您无需在用户代码中担心它)。
回答by Pete
It is correct but could be made more efficient.
这是正确的,但可以提高效率。
You could use the boost multidimensional arrays: http://www.boost.org/doc/libs/1_47_0/libs/multi_array/doc/user.html
您可以使用 boost 多维数组:http: //www.boost.org/doc/libs/1_47_0/libs/multi_array/doc/user.html
Or, you can implement your own class for it and handle the indexing yourself. Perhaps something like this (which is not well tested):
或者,您可以为它实现自己的类并自己处理索引。也许是这样的(没有经过很好的测试):
#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_;
};
回答by thiton
While the points the other answers made were very correct (don't dynamically allocate the vector via new, but rather let the vector do the allocation), if you are thinking terms of vectors and matrices (e.g. linear algebra), you might want to consider using the Eigen matrix library.
虽然其他答案提出的观点非常正确(不要通过 new 动态分配向量,而是让向量进行分配),但如果您正在考虑向量和矩阵的术语(例如线性代数),您可能想要考虑使用特征矩阵库。
回答by Mayukh Sarkar
Sometimes you don't want to fill your stack and your memory requirement is large. Hence you may want to use vector> created dynamically especially while creating a table of a given row and col values.
有时您不想填满堆栈并且您的内存需求很大。因此,您可能希望使用动态创建的 vector>,尤其是在创建给定行和列值的表时。
Here is my take on this in C++11
这是我在 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;
}
回答by visitor
You don't allocate containers dynamically. They can automatically manage memory for you if they themselves are not manually managed.
您不会动态分配容器。如果它们本身不是手动管理的,它们可以自动为您管理内存。
A vector grows when you add new items with push_back
(or insert
), you can choose its size from the start with arguments to the constructor, and you can resize it later with the resize
method.
当您使用push_back
(或insert
)添加新项目时,向量会增长,您可以从一开始使用参数到构造函数选择其大小,并且您可以稍后使用该resize
方法调整其大小。
Creating a vector of vectors with your sizes with the constructor looks like this:
使用构造函数创建具有您的大小的向量向量如下所示:
std::vector< std::vector<double> > matrix(size, std::vector<double>(sizeY));
This means: size
instances of a std::vector<double>
, each containing sizeY
doubles (initialized to 0.0).
这意味着: a 的size
实例std::vector<double>
,每个实例都包含sizeY
双精度值(初始化为 0.0)。
回答by foxy
If you don't need to resize the array sizes at run time, then you can just use standard arrays (allocated at runtime)!
如果您不需要在运行时调整数组大小,那么您可以只使用标准数组(在运行时分配)!
However, if you do need to resize arrays at runtime, then you can use the following (revised) code:
但是,如果您确实需要在运行时调整数组大小,则可以使用以下(修改后的)代码:
#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));
In essence, all I've done is remove a single bracket ((
).
从本质上讲,我所做的只是删除了一个括号 ( (
)。