2015-11-06 33 views
4

比方说,我有一个这样的结构:通过值传递的C++向量:我得到它的权利?

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> &parameterVector 

的功能得到了参考myVector存储在堆栈中,所以我现在都存储在堆栈中的变量,引用也存储在myVector对象在堆栈中,它包含一个指向存储在堆中的实际元素数组的指针。

这是正确的吗?

我有几个疑惑这里:

  1. 做实际的元素,会存储在一个静态数组(由C继承而来的,用方括号表示)在堆中?
  2. myVector对象是否只有一个指向第一个元素的指针,或者它有多个指向每个元素的指针?
  3. 因此,按值传递一个向量不会带来很大的问题,因为唯一被复制的是矢量对象,但不是实际的元素。是这样吗?
  4. 如果我弄错了所有的东西,并且实际的元素也被复制以及通过值传递向量参数,那么为什么C++允许这样做,考虑到它会阻止它与静态数组? (据我所知,静态数组总是作为参考传递给第一个元素)。

谢谢!

+0

如果按值传递一个向量,则元素也会被复制 –

+2

声明'vector&parameterVector'声明'parameterVector'是'typeA'元素的向量的引用*,而不是指针。 –

+1

而关于'vector myVector(4,100)',那不是一个有效的声明。它试图创建一个由四个元素组成的向量,每个元素初始化为“100”。但是你不能将'typeA'对象初始化为'100'。 –

回答

2

是否将实际元素存储在堆中的静态数组中(从C中继承,用方括号表示)?

典型地,该向量的元素使用的是动态数组存储在自由存储区等

some_type* some_name = new some_type[some_size] 

是否myVector对象仅具有一个指针的第一个元素,或它具有多个指针到每一个元素?

通常情况下,一个向量将有一个指向第一个元素的指针,一个大小变量和一个容量。它可能有更多,但这些是实现细节,并没有被标准定义。

因此,按值传递一个向量不会带来很大问题,因为唯一被复制的是矢量对象,而不是实际元素。是这样吗?

复制矢量是否为O(N)操作,因为它必须复制矢量的每个元素。如果没有,那么你将有两个向量使用相同的底层数组,如果一个被破坏,那么它会从另一个下面删除数组。

+3

*“将它看作是按值传递的对象”*,除非修改它会影响函数外部的某些内容。 –

+1

“把它看作是一个按值传递的对象” - ** no **:把它当作通过引用传递的对象,因为这就是发生的事情。 –

1
  1. 做实际的元件获取存储在一个静态数组(由C继承的那些,用方括号表示)在堆中?

std::vector<>将在堆中的所有要素分配内存,因为,您使用标准分配器。它将管理该内存并在必要时重新分配。所以不,没有静态数组。它更像是在C中处理动态数组,但没有所有陷阱。

如果您正在寻找现代化的C阵列替代品,请看std::array<>。请注意,std::array<>也会复制所有元素。如果这是你的意思,请通过参考。

  • 是否myVector对象仅具有一个指针的第一个元素,或它具有多个指针的元素中的每一个?
  • std::vector通常是一个指向第一个元素,尺寸和用于内部使用几个更多的比特。但细节实际上是特定于实现的。

  • 因此,通过值传递一个矢量不会造成太大的问题,因为该被复制的唯一事情是矢量对象,但不是实际的元件。是这样吗?
  • 否。只要将矢量对象复制到另一个矢量对象,所有元素都将被复制。

  • 如果我得到整个事情错误并通过一个向量参数由值时的实际元素被复制,以及,那么为什么C++实现这一点,考虑到它具有阻止它静态数组?(据我所知,静态数组总是作为参考传递给第一个元素)。
  • “静态数组”是C-Legacy。你应该在新代码中不再使用它们。如果你想通过引用传递一个向量,那么这样做并不会复制任何内容。万一你想要移动向量,移动它,而不是复制它。每当你告诉编译器,你想复制一个对象,它会。

    好吧,为什么这样呢?

    C行为在某种程度上与其他语言不一致。当你传递一个int时,它会被复制,当你传递一个结构时,它将被复制,当你传递一个指针时,它将被复制,但是当你传递一个数组时,数组不会被复制,而是一个指针到它的第一个元素。

    所以C++的方式更加一致。通过价值复制一切,通过参考不。使用C++ 11移动构造函数,可以通过移动它们来传递对象。这意味着,原始矢量将保留为空,而新的矢量已经接管了原始内存块的责任。