在for循环内创建指针会导致指向相同的内存地址 [英] Creating pointers inside a for loop results in pointing to same memory address

查看:114
本文介绍了在for循环内创建指针会导致指向相同的内存地址的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个对象,试图对该对象进行一些次更改,然后尝试复制任意次.我想将指向这些重复对象的指针存储在 std :: vector 中.我正在使用 for 循环尝试获得结果.但是,我注意到的是,循环退出后, std :: vector< T *> 指向相同的地址.我尝试使用 std :: string 复制对象的尝试,但效果相同.这是我的代码段.

I have an object that I am trying to duplicate for any number of times with some minor changes to that object. I want to store pointers to those duplicated objects in a std::vector. I am using a for loop to try and achieve the result. However, what I notice is that the std::vector<T *> is pointing to the same address after the loop exits. I tried this attempt to duplicate objects with std::string and I see the same effects. Here's my code snippet.

int main() {
  auto name = new std::string("fido");

  const int size = 3;
  std::vector<std::string *> names;
  names.reserve(size);

  for (int i = 0; i < size; i++) {
    std::string n = *name + " " + std::to_string(i);
    names.push_back(&n);
  }

  // nothing from this loop prints out
  for (auto n : names) {
    std::cout << *n << std::endl;
  }

  return 0;
}

当我将代码放在调试器中时,我看到 names 正在存储所有指向相同内存地址的指针: 0x7ffffffeead0 .对我在这里做错的任何想法吗?

When I place the code in a debugger, I see that names is storing pointers all to the same memory address: 0x7ffffffeead0. Any ideas on what I am doing wrong here?

我修改了代码以存储字符串向量,然后循环遍历每个字符串,创建指向每个字符串地址的指针,如下所示.这种方法也不起作用.指针的向量都仍然指向同一地址.尽管这次,它们都指向最后一个字符串的地址.

I modified the code to store a vector of strings, and then to loop through each string, creating a pointer to each string's address as follows. This approach also does not work. The vector of pointers all still point to the same address; although this time, they all point to the address of the last string.

int main() {
  auto name = new std::string("fido");

  const int size = 3;
  std::vector<std::string *> pointers;
  std::vector<std::string> names;

  names.reserve(size);
  pointers.reserve(size);

  for (int i = 0; i < size; i++) {
    std::string n = *name + " " + std::to_string(i);
    names.push_back(n);
  }

  for (int i = 0; i < size; i++) {
    auto n = names.at(i);
    auto p = &n;
    pointers.push_back(p);
  }

  for (auto n : names) {
    std::cout << n << std::endl;
  }

  for (auto n : pointers) {
    std::cout << *n << std::endl;
  }

  return 0;
}

但是,在第三次尝试中,我将代码修改如下.请注意,对于按索引访问元素的位置,我使用了& 运算符.在这里,我确实得到了一个 std :: vector< std :: string *> 指向不同的地址(正确对应于字符串的向量).

Yet, in a third attempt, I modify the code as follows. Note that I use the & operator against where I access the element by index. Here, I do get a std::vector<std::string *> that points to different addresses (corresponding correctly to the vector of strings).

int main() {
  auto name = new std::string("fido");

  const int size = 3;
  std::vector<std::string *> pointers;
  std::vector<std::string> names;

  names.reserve(size);
  pointers.reserve(size);

  for (int i = 0; i < size; i++) {
    std::string n = *name + " " + std::to_string(i);
    names.push_back(n);
  }

  for (int i = 0; i < size; i++) {
    auto p = &names.at(i); // using address operator like this "works"
    pointers.push_back(p);
  }

  for (auto n : names) {
    std::cout << n << std::endl;
  }

  for (auto n : pointers) {
    std::cout << *n << std::endl;
  }

  return 0;
}

最后,我终于得到了这个更简洁的例子.在这里,我在每个循环上创建一个新的指针.

Lastly, I finally get this more concise example to work. Here, I create a new pointer on every loop.

int main() {
  auto name = new std::string("fido");

  const int size = 3;
  std::vector<std::string *> names;
  names.reserve(size);

  for (int i = 0; i < size; i++) {
    auto x = new std::string(*name + " " + std::to_string(i));
    names.push_back(x);
  }

  for (auto n : names) {
    std::cout << *n << std::endl;
  }

  return 0;
}

for循环和指针上是否缺少某些内容?任何指向C ++范围规则的指针(无双关语)将不胜感激.

Is there something on for-loops and pointers that I am missing here? Any pointers (no pun intended) to scoping rules for C++ would be appreciated.

推荐答案

但是,我注意到的是,循环退出后std :: vector指向相同的地址.

However, what I notice is that the std::vector is pointing to the same address after the loop exits.

对我在这里做错的任何想法吗?

Any ideas on what I am doing wrong here?

for (int i = 0; i < size; i++) {
    std::string n = *name + " " + std::to_string(i);

在这里, n 是一个自动变量. n -像所有具有自动存储功能的对象一样,将在范围的末尾(即在迭代结束时)销毁.

Here, n is an automatic variable. n - like all objects with automatic storage, will be destroyed at the end of the scope, i.e. at the end of the iteration.

    names.push_back(&n);

在这里,您获取自动对象的地址并将其存储在向量中.

Here, you take the address of the automatic object and store it inside a vector.

}

在这里,迭代结束,下一个迭代开始. n 已被破坏,向量中的指针无效.在下一次迭代中,将创建一个新的 n 对象.由于前一个 n 被销毁,因此下一个对象可以使用相同的内存.

Here, the iteration ends and the next one begins. n has been destroyed and the pointer in the vector is invalid. In the next iteration, a new n object is created. Since the previous n was destroyed, the same memory can be used for the next object.

for (auto n : pointers) {
    std::cout << *n << std::endl;

在这一行上,您尝试通过无效的指针访问不存在的字符串,并且程序的行为未定义.

On this line, you attempt to access non-existing string through an invalid pointer and the behaviour of the program is undefined.

在您的第二次和第三次尝试中,相同的模式仍然存在.

The same pattern persists through your second and third attempt.

在包括第四个示例在内的所有示例中,您都会泄漏内存.

In all your examples including the fourth one, you leak memory.

我有一个对象要重复任意次数

I have an object that I am trying to duplicate for any number of times

您可以将字符串存储在 std :: vector< std :: string> 中.您可以像这样复制这样的向量:

You can store strings in std::vector<std::string>. You can duplicate such vector like this:

std::vector<std::string> names;
// insert names here

std::vector<std::string> duplicates = names;

这篇关于在for循环内创建指针会导致指向相同的内存地址的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆