可以在“堆栈”上分配的向量从函数传递到函数吗?

时间:2012-04-06 18:05:30

标签: c++ memory-management vector

我知道当函数完成执行时,在函数的堆栈上分配的变量变得不可访问。但是,无论分配方式如何,矢量类型都会在堆上分配它们的元素。例如,

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;
}

在main函数中使用向量A时,是否会出现内存访问问题?我试了好几次,他们都正常工作,但我很害怕这可能只是运气。

我看到它的方式是,向量A在堆上分配它的元素,但是它在堆栈本身上分配了一些“开销”参数(可能是向量的大小)。因此,如果这些参数被另一个分配覆盖,则在main函数中使用向量可能会导致内存访问问题。有什么想法吗?

3 个答案:

答案 0 :(得分:4)

当你做“返回A”时你按值返回,所以你得到了一个向量的副本--C ++创建一个新的实例并在其上调用copy constructor或operator =。因此,在这种情况下,分配内存的位置并不重要,因为您无论如何都必须复制它并销毁旧的副本(尽管有一些可能的优化)。

向量(以及所有其他STL容器)中的数据也会按值移动,因此您存储整数的副本,而不是指向它们的指针。这意味着您的对象可以在任何容器操作中多次复制,并且必须正确实现复制构造函数和/或赋值运算符。 C ++默认为你生成那些(只是在所有成员变量上调用copy ctor),但它们并不总是做正确的事情。

如果要在STL容器中存储指针,请考虑使用共享指针包装器(std :: shared_ptr或boost :: shared_ptr)。它们将确保正确处理内存。

答案 1 :(得分:1)

是的,它将正常工作,因为元素的内存已分配,并且将用于构建vector<int> A =变量。但是,性能方面,这不是最好的主意。

我建议将您的功能更改为以下内容

void initVector(vector<int>& a, int size) 

有关使用情况的其他参考,请参阅Returning a STL vector from a function…[C++] Returning Vector from Function

有关性能的其他参考(使用C ++ 11),请参阅Proper way (move semantics) to return a std::vector from function calling in C++0x

答案 2 :(得分:0)

C ++ vector实际上有两块内存,它们与一个指针链接在一起。第一个是堆栈,第二个是堆。因此,您在单个对象中具有堆栈和堆的功能。

std::vector<int> vec;
vec.push_back(10);
vec.push_back(20);
vec.push_back(30);
std::cout << sizeof(vec) << std::endl;

运行该代码后,您会注意到堆栈区域不包含元素,但它仍然存在。因此,当您将向量从函数传递到另一个函数时,您将需要操纵堆栈区域,并且矢量将像任何其他基于堆栈的对象一样被复制。