结构向量的 C++ 正确方法论
C++ Proper Methodology for vectors of structs
所以想象一下我有一个结构
struct Square{
int width;
int height;
};
然后我的代码中某处有一个函数
void create_vec_squares(std::vector<Square> &dest){
for(int i = 0; i < 10; i++){
//create squares and put then into the destination vector
}
}
在 C++ 中执行此操作的正确方法是什么?我知道一些 C,我的直接想法是使用 malloc 等内存分配技术。但是,我需要输入一个 void delete_vec_squares(...) 以确保正确释放内存。
我想知道这种方法是否会出现任何问题
void create_vec_squares(std::vector<Square> &dest){
for(int i = 0; i < 10; i++){
int val1,val2;
//generate some values for squares
...
//end generation
dest.push_back({val1, val2});
}
}
根据我的理解,不是在堆上分配内存,而是将结构简单地压入堆栈,不需要手动内存分配技术;
instead of allocating memory on the heap, the structures will simply be pushed onto the stack and there will be no need for manual memory allocation techniques;
你是对的。当你push_back时,你只需要push_back,因为
std::vector<T>::push_back(const T & val);
是基于复制的。
您的 Square
对象将安全地保存在 std::vector<Square>
范围之外。
如果您在 Square
中进行一些分配,那么 Square::~Square()
的工作就是释放需要的东西。
push_back
是一种向量方法,它在向量的末尾添加一个新元素,在其当前最后一个元素之后。
您可以执行以下操作:
void create_vec_squares(std::vector<Square> &dest){
for(int i = 0; i < 10; i++){
//create an object Square and lets call it newSquare, then you can use push_back
dest.push_back(newSquare);
//this will add your object newSquare at the end of vector dest
}
}
如果您想完全清空向量,可以使用 dest.clear()
。通过使用包含的方法,它可以减少对象管理不当的可能性 vector
,并且通常更安全。
I was wondering if any issues could arise with this method
void create_vec_squares(std::vector<Square> &dest){
for(int i = 0; i < 10; i++){
int val1,val2;
//generate some values for squares
...
//end generation
dest.push_back({val1, val2});
}
}
此方法的唯一问题是您的代码可能不可移植。有些地方还卡在C++03编译器,没有统一初始化
关于正确的方法论,没有一种正确的方法论。当你可以使用它时,统一初始化很棒。你不能总是使用它(即使在 C++11 和更高版本中)。有时您需要使用显式构造函数,有时您需要在将项目添加到容器之前对其进行操作。仍然不需要 new
和 delete
。只需声明一个局部变量并将其推回容器即可。
当您知道要将一大堆对象放到矢量上时,为传入的一船负载预留一些 space 可能是有利的。您的代码包含大量 (10000) 个对象,而不仅仅是 10 个:
void create_vec_squares(std::vector<Square> &dest){
dest.reserve(dest.size() + 10000);
for(int i = 0; i < 10000; i++){
int val1,val2;
//generate some values for squares
...
//end generation
dest.push_back({val1, val2});
}
}
如果您确切知道 dest
中要设置十个对象,则以下方法可能更清晰、更快速:
struct Square{
int width;
int height;
Square & set(int p_width, int p_height) {
width = p_width; height = p_height;
return (*this);
}
};
typedef std::vector<Square> Square_vec;
void create_vec_squares(Square_vec & dest){
//create squares
dest.reasize(10);
for(Square_vec::iterator v_i = dest.begin(), v_e = dest.end(); v_i < v_e; ++v_i){
// and put then into the destination vector
v_i->set(val1, val2); //The already created Square object is set whithout temporary.
//Or if you have common temporay Square object:
*v_i = tmpSquare;
}
}
重构的下一步可能是创建一个函子来填充 Square_vec,从 <algorithm>
而不是 for(Square_vec::iterator ...
循环中代入 for_each
函数。
所以想象一下我有一个结构
struct Square{
int width;
int height;
};
然后我的代码中某处有一个函数
void create_vec_squares(std::vector<Square> &dest){
for(int i = 0; i < 10; i++){
//create squares and put then into the destination vector
}
}
在 C++ 中执行此操作的正确方法是什么?我知道一些 C,我的直接想法是使用 malloc 等内存分配技术。但是,我需要输入一个 void delete_vec_squares(...) 以确保正确释放内存。
我想知道这种方法是否会出现任何问题
void create_vec_squares(std::vector<Square> &dest){
for(int i = 0; i < 10; i++){
int val1,val2;
//generate some values for squares
...
//end generation
dest.push_back({val1, val2});
}
}
根据我的理解,不是在堆上分配内存,而是将结构简单地压入堆栈,不需要手动内存分配技术;
instead of allocating memory on the heap, the structures will simply be pushed onto the stack and there will be no need for manual memory allocation techniques;
你是对的。当你push_back时,你只需要push_back,因为
std::vector<T>::push_back(const T & val);
是基于复制的。
您的 Square
对象将安全地保存在 std::vector<Square>
范围之外。
如果您在 Square
中进行一些分配,那么 Square::~Square()
的工作就是释放需要的东西。
push_back
是一种向量方法,它在向量的末尾添加一个新元素,在其当前最后一个元素之后。
您可以执行以下操作:
void create_vec_squares(std::vector<Square> &dest){
for(int i = 0; i < 10; i++){
//create an object Square and lets call it newSquare, then you can use push_back
dest.push_back(newSquare);
//this will add your object newSquare at the end of vector dest
}
}
如果您想完全清空向量,可以使用 dest.clear()
。通过使用包含的方法,它可以减少对象管理不当的可能性 vector
,并且通常更安全。
I was wondering if any issues could arise with this method
void create_vec_squares(std::vector<Square> &dest){
for(int i = 0; i < 10; i++){
int val1,val2;
//generate some values for squares
...
//end generation
dest.push_back({val1, val2});
}
}
此方法的唯一问题是您的代码可能不可移植。有些地方还卡在C++03编译器,没有统一初始化
关于正确的方法论,没有一种正确的方法论。当你可以使用它时,统一初始化很棒。你不能总是使用它(即使在 C++11 和更高版本中)。有时您需要使用显式构造函数,有时您需要在将项目添加到容器之前对其进行操作。仍然不需要 new
和 delete
。只需声明一个局部变量并将其推回容器即可。
当您知道要将一大堆对象放到矢量上时,为传入的一船负载预留一些 space 可能是有利的。您的代码包含大量 (10000) 个对象,而不仅仅是 10 个:
void create_vec_squares(std::vector<Square> &dest){
dest.reserve(dest.size() + 10000);
for(int i = 0; i < 10000; i++){
int val1,val2;
//generate some values for squares
...
//end generation
dest.push_back({val1, val2});
}
}
如果您确切知道 dest
中要设置十个对象,则以下方法可能更清晰、更快速:
struct Square{
int width;
int height;
Square & set(int p_width, int p_height) {
width = p_width; height = p_height;
return (*this);
}
};
typedef std::vector<Square> Square_vec;
void create_vec_squares(Square_vec & dest){
//create squares
dest.reasize(10);
for(Square_vec::iterator v_i = dest.begin(), v_e = dest.end(); v_i < v_e; ++v_i){
// and put then into the destination vector
v_i->set(val1, val2); //The already created Square object is set whithout temporary.
//Or if you have common temporay Square object:
*v_i = tmpSquare;
}
}
重构的下一步可能是创建一个函子来填充 Square_vec,从 <algorithm>
而不是 for(Square_vec::iterator ...
循环中代入 for_each
函数。