【问题标题】:std::vector and its initialization pointer consistencestd::vector 及其初始化指针的一致性
【发布时间】:2015-10-23 08:44:22
【问题描述】:

我给出以下代码来说明我的问题,你可以在http://cpp.sh/

// Example program
#include <iostream>
#include <string>
#include <vector>

int main()
{
  int *p;
  p = new int [10];
  for(int i=0; i<10; i++)
      p[i] = i;

  std::vector<int> vecArray(p,p+10);
  vecArray[3]=300;

  for(int i=0; i<10; i++)
      std::cout<<vecArray[i]<<std::endl;

    for(int i=0; i<10; i++)
      std::cout<<p[i]<<std::endl;

  delete []p;
}

从代码中我们可以看出,在使用指针p初始化向量vecArray之后,当向量的内容发生变化时,不会影响指针中的内容。我的问题是:vctor 的内容怎么可能总是与指针相同?

【问题讨论】:

  • 您希望p[3] 中的值在vecArray[3]=300; 之后更改吗?
  • 所有容器类都存储数据的硬拷贝,否则它们将毫无用处。
  • @SingerOfTheFall 是的。
  • vector&lt;&gt;要点 是它能够在添加元素时动态调整大小。如果它需要更多内存,vector&lt;&gt; 会为其包含的数据分配新内存,将旧数据复制到新内存位置,然后释放旧内存。应该清楚的是,在这一点上vector&lt;&gt; 仍然无法引用与p 相同的内存,即使您设法像最初那样设置它们。 --- 我怀疑我们在这里查看的是 X-Y 问题。 原始问题是什么,您试图用这个向量引用相同的内存作为数组作为解决方案来解决?

标签: c++ pointers vector stl


【解决方案1】:

向量的内容是动态分配数组内容的副本。

您需要了解,您的示例代码分配了 10 个整数两次次,一次是当您显式调用 new 时,另一次是在您构造 vector 时。

您可以让两者共享相同的内存,例如,首先构建您的向量,然后获取指向其数据的指针:

#include <iostream>
#include <vector>

int     main(void)
{
  std::vector<int> vecArray(10);

  for(int i=0; i<10; i++)
    vecArray[i] = i;

  const int* p = vecArray.data();

  vecArray[3]=300;

  for(int i=0; i<10; i++)
    std::cout<<vecArray[i]<<std::endl;

  for(int i=0; i<10; i++)
    std::cout<<p[i]<<std::endl;
}

【讨论】:

  • 应该注意,由于重新分配,在对向量进行一些操作(例如,插入)后,指向vector::data() 返回的内部数据的指针和迭代器都不能保证有效。
  • 请注意p 可以在修改vecArray 时指向无效内存,例如通过添加新元素。
  • @Drax 谢谢,这是一个不错的解决方案。但就我而言,我希望向量共享指针。在您的示例中,它是共享向量的指针。
  • @feelfree 你不能那样做,vector 管理它自己的内存,而不是你在其他地方自己创建的内存(除了可能使用自定义分配器,但不确定那是你想要的):)
【解决方案2】:

您可以使您的vector 包含指向int 的指针。

你推入你的动态分配数组的向量地址。

#include <iostream>
#include <string>
#include <vector>

int main()
{
  int *p;
  p = new int [10];
  for(int i=0; i<10; i++)
      p[i] = i;

  std::vector<int*> vecArray;
  for(int i=0; i<10; i++)
      vecArray.push_back(&p[i]); //push_back addresses in the vector

  p[3]=300; //you can also: *(vecArray[3])=300;

  for(int i=0; i<10; i++)
      std::cout<<*vecArray[i]<<std::endl; // Deference your pointer to get the value

  for(int i=0; i<10; i++)
      std::cout<<p[i]<<std::endl;

  delete []p;
}

【讨论】:

    【解决方案3】:

    这是vector 的构造函数,它使用一个范围

    template <class InputIterator> vector (InputIterator first, InputIterator last, const allocator_type& alloc = allocator_type());

    这是描述:

    Range constructor: Constructs a container with as many elements as the range [first,last), with each element emplace-constructed from its corresponding element in that range, in the same order.

    它从对应的元素中说 emplace-constructed。所以这意味着它创建了指针指向的对象的新副本。

    这就是为什么The underlying type an std::vector uses must be CopyAssignable

    因此,作为摘要向量,从数组元素创建一组副本。因此,如果您更改一组中的任何元素,它不会反映在另一组中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-06-06
      • 1970-01-01
      • 2013-07-13
      • 2012-06-09
      • 1970-01-01
      • 2012-08-07
      • 1970-01-01
      相关资源
      最近更新 更多