在"stack"上分配的向量可以在函数之间传递吗?
Can a vector allocated on the "stack" be passed from function to function?
我知道,当函数完成执行时,在函数堆栈上分配的变量将变得不可访问。然而,向量类型在堆上分配它们的元素,无论它们是如何分配的。例如,
vector<int> A;
将在堆而不是堆栈上为其元素分配空间。
我的问题是,假设我有以下代码:
int main(int argc, char *argv[]) {
// initialize a vector
vector<int> A = initVector(100000);
// do something with the vector...
return 0;
}
// initialize the vector
vector<int> initVector(int size) {
vector<int> A (size); // initialize the vector "on the stack"
// fill the vector with a sequence of numbers...
int counter = 0;
for (vector<int>::iterator i = A.begin(); i != A.end(); i++) {
(*i) = counter++;
}
return A;
}
在主函数中使用向量A时,我会遇到内存访问问题吗?我试了好几次,它们都正常工作,但我担心这可能只是运气。
在我看来,向量A在堆上分配元素,但它在堆栈本身上分配了一些"开销"参数(可能是向量的大小)。因此,如果这些参数被另一个分配覆盖,那么在主函数中使用向量可能会导致内存访问问题。有什么想法吗?
当你执行"return A;"时,你会按值返回,所以你会得到向量的副本——C++会创建一个新实例,并在它上调用copy-constructor或operator=。所以在这种情况下,内存分配在哪里并不重要,因为你无论如何都必须复制它并销毁旧副本(尽管有一些可能的优化)。
向量(以及所有其他STL容器)中的数据也会按值移动,因此您存储整数的副本,而不是指向它们的指针。这意味着您的对象可以在任何容器操作中多次复制,并且它们必须正确实现复制构造函数和/或赋值运算符。默认情况下,C++会为您生成这些(只是对所有成员变量调用copy-ctor),但它们并不总是做正确的事情。
如果要将指针存储在STL容器中,请考虑使用共享指针包装器(std::shared_ptr或boost::shared-ptr)。它们将确保正确处理内存。
是的,它将正常工作,因为元素的内存已分配,这将用于构建vector<int> A =
变量。然而,就性能而言,这并不是最好的主意。
我建议通过将您的功能更改为如下
void initVector(vector<int>& a, int size)
有关用法的其他参考,请参阅从函数返回STL矢量…和[C++]从函数返回矢量。
有关性能的其他参考(使用C++11),请参阅从C++0x 中的函数调用返回std::vector的正确方式(移动语义)
C++向量实际上有两块内存,它们用一个指针链接。第一个在堆栈中,第二个在堆中。因此,在单个对象中同时具有堆栈和堆的特性。
std::vector<int> vec;
vec.push_back(10);
vec.push_back(20);
vec.push_back(30);
std::cout << sizeof(vec) << std::endl;
运行该代码后,您会注意到堆栈区域不包含元素,但它仍然存在。因此,当您将向量从一个函数传递到另一个函数时,您需要操作堆栈区域,并且向量将像任何其他基于堆栈的对象一样被复制。
- C++ 使用 assign 函数的字符串与直接使用 '=' 更改值的字符串之间的区别
- 在 const 函数中通过引用和指针返回之间的区别
- 在两台机器之间进行时间戳的最佳c++chrono函数是什么
- 使用.find函数在c++中查找字符和另一个字符之间的大小
- 构造函数和转换运算符之间的重载解析
- C++LinkedList问题.数据类型之间存在冲突?没有匹配的构造函数
- 编译器如何在使用SFINAE的函数和标准函数之间确定两者是否可行
- 为什么 c++(g++) 不允许模板返回类型和函数名称之间有空格?
- 填充上编译器生成的复制构造函数之间的不一致
- 析构函数和'delete'之间的区别
- 为什么不允许成员函数和非成员函数之间的函数重载?
- 函数签名与调用的函数不匹配,常量字符[]和字符*之间的区别?
- 如何在"push_*()"和"emplace_*()"函数之间进行选择?
- 内联函数的函数本地静态对象是否在共享对象文件之间共享?
- 派生类(构造函数具有参数)和基类(构造函数缺少参数)之间没有可行的转换
- 在"template"和函数声明之间使用:template<typename trait> using tr = base_trait<trait> void fn(tr::t
- 在 C 和 C++ 中作为函数参数,int **a 和 int a[][] 之间有什么确切的区别
- 定义类模板构造函数的两种方法之间的区别
- 仅具有运算符()的结构和普通函数之间的实际区别
- 可变/非可变模板之间函数类型衰减的不一致性