我们说我有这样的结构:
struct typeA
{
long first;
string second
double third;
};
如果我宣布
typeA myArray[100];
然后myArray存储在堆栈中,消耗sizeof(typeA)* 100字节的垃圾数据(直到我存储一些实际数据,至少)。
每当我将此数组作为参数传递时,我总是会将指针传递给堆栈中第一个元素。所以指针从堆栈到堆栈。
但如果我宣布
vector<int> myVector (4, 100);
然后myVector对象实际存储在堆栈中,它包含一个指向存储在堆中的4 * sizeof(int)字节数组的第一个元素的指针,其中存储了实际数据。所以指针从堆栈变为堆。
每当我将此向量作为参数传递时,如果我将它添加到参数列表中,如下所示:
vector<int> parameterVector
该函数获取myVector对象的副本并将其存储在堆栈中。
但如果我这样做:
vector<int> ¶meterVector
该函数获取存储在堆栈中的对myVector的引用,所以我现在有一个存储在堆栈中的变量,引用一个也存储在堆栈中的myVector对象,其中包含一个指向数组的指针存储在堆中的实际元素。
这是对的吗?
我有点怀疑:
谢谢!
答案 0 :(得分:2)
实际的元素是否存储在堆中的静态数组(从C继承,用方括号表示)中?
通常,矢量的元素使用动态数组(如
)存储在空闲存储中some_type* some_name = new some_type[some_size]
myVector对象是否只有一个指向第一个元素的指针,或者它有多个指向每个元素的指针?
通常,向量将具有指向第一个元素,大小变量和容量的指针。它可能有更多,但这些是实现细节,并没有由标准定义。
因此,按值传递矢量并不会造成太大问题,因为复制的唯一内容是矢量对象,而不是实际的元素。是这样吗?
没有。复制向量是O(N)操作,因为它必须复制向量的每个元素。如果没有那么你将有两个使用相同底层数组的向量,如果一个被销毁,那么它将从另一个下面删除数组。
答案 1 :(得分:1)
- 实际的元素是否存储在堆中的静态数组(从C继承,用方括号表示)中?
醇>
std::vector<>
将在堆上为您使用标准分配器的所有元素分配内存。它将管理该内存并在必要时重新分配。所以不,没有静态数组。它更像你在C中处理动态数组,但没有所有的陷阱。
如果您正在寻找C-Arrays的现代替代品,请查看std::array<>
。请注意,std::array<>
也会复制所有元素。如果这就是你的意思,请参考。
- myVector对象是否只有一个指向第一个元素的指针,或者它有多个指向每个元素的指针?
醇>
std::vector
通常是指向第一个元素的指针,一个大小和一些内部使用的位。但细节实际上是特定于实现的。
- 因此,按值传递矢量并不会造成很大的问题,因为复制的唯一内容是矢量对象,而不是实际的元素。是这样吗?
醇>
没有。每当矢量对象被复制到另一个矢量对象时,所有元素都将被复制。
- 如果我把整个事情搞错了,并且在按值传递矢量参数时也会复制实际元素,那么为什么C ++会允许这样做,考虑到它会阻止静态数组呢? (据我所知,静态数组总是作为第一个元素的引用传递。)
醇>
&#34;静态数组&#34;是C-Legacy。您不应该在新代码中再使用它们。如果您想通过引用传递矢量,请执行此操作,不会复制任何内容。如果您想要移动矢量,请移动它,而不是复制它。每当你告诉编译器时,你想复制一个对象,它就会。
好的,为什么会这样?
C行为在某种程度上与语言的其他部分不一致。当你传递一个int时,它会被复制,当你传递一个struct时,它会被复制,当你传递一个指针时,它会被复制,但是当你传递一个数组时,数组不会被复制,而是一个指针到它的第一个元素。
所以C ++的方式更加一致。通过值复制一切,通过引用传递不是。使用C ++ 11移动构造函数,可以通过移动对象来传递对象。这意味着,原始向量将保留为空,而新的向量将接管原始内存块的负责。