在 for 循环中创建的对象具有相同的地址

Object created in for-loop has same address

本文关键字:地址 对象 循环 创建 for      更新时间:2023-10-16

我正在尝试创建一个自己的列表类,该类具有固定大小并且可以存储整数。只是为了学习目的。

我是这样做的: 我有一个名为 Item 的结构,它保存数据(要存储的整数),以及指向列表中下一项的指针。 当列表初始化时,我首先将 x 数量的空项目添加到列表中。

迭代 (n-1) 中声明的项的地址存储在缓冲区中,以便可以将迭代 n 中项的地址设置为上一次迭代 (n-1) 中的项的下一个。 这将将所有项目相互链接。

并且第一项的地址也被保存,作为代码后面整个列表的访问点。

但它并没有真正起作用;这是我的代码:

#include <iostream>
class List {
public:
//Item-object needed to store
//elements
struct Item {
int data = 0;
Item* next = nullptr;
};
//Constructor
//creates a list of fixed size
List(int size) {
//Filling up with empty items
for (int i = 0; i < size; i++) {
Item item;
//Storing iterator in item (just for testing purposes)
item.data = i;
//If first item,
//store start-address
//set buffer to start address
if (i == 0) 
this->start = &item;
//Setting current item as nextptr
//for previous item in buffer 
if (i > 0)
this->buffer->next = &item;
//Storing current address in buffer
this->buffer = &item;
//Outputting address and value (just for testing purposes)
//std::cout << "Address: " << &item << " -> " << item.data << std::endl;
}
}
Item* getFirstItemAddress() {
return this->start;
}
private:
//Holding address of first item
Item* start = nullptr;
//Buffer holding temporary address
Item* buffer = nullptr;
};
int main() {
List list(5);
//Printing out
List::Item* current = list.getFirstItemAddress();
while (current->next) {
std::cout << current->data << std::endl;
current = current->next;
}
return 0;
}

这是输出:

Testing output:
1168769696
-1064971727
Segmentation fault

但是,当我取消注释测试行 37 时,这是输出:

Address: 0x7ffe54015cf0 -> 0
Address: 0x7ffe54015cf0 -> 1
Address: 0x7ffe54015cf0 -> 2
Address: 0x7ffe54015cf0 -> 3
Address: 0x7ffe54015cf0 -> 4
Testing output:
1648675776
1648572376
1646105840
1226279756
Segmentation fault

首先我不明白输出如何如此彻底地改变"测试输出"的输出......

无论如何,分段错误信息:

(gdb) run
Starting program: /home/niel/Desktop/listTest/main 
Address: 0x7fffffffe0a0 -> 0
Address: 0x7fffffffe0a0 -> 1
Address: 0x7fffffffe0a0 -> 2
Address: 0x7fffffffe0a0 -> 3
Address: 0x7fffffffe0a0 -> 4
Testing output:
-136467520
-136570920
-139037456
1226279756
Program received signal SIGSEGV, Segmentation fault.
0x000000000040092e in main () at main.cpp:62
62              std::cout << current->data << std::endl;

不知道为什么当前>数据会产生分割错误,因为我为每个元素提供了数据!

但最让我困扰的是:

Address: 0x7fffffffe0a0 -> 0
Address: 0x7fffffffe0a0 -> 1
Address: 0x7fffffffe0a0 -> 2
Address: 0x7fffffffe0a0 -> 3
Address: 0x7fffffffe0a0 -> 4

每个项目都有相同的地址,当然,这不是我的意思。在迭代中创建的每个项都应是具有另一个地址的另一个项。 这是否与 Item 被声明为本地有关,并且由于该原因,对象存储在堆栈上而不是可用空间中?我尝试使用"新"关键字,但没有用!

TL;DR1) 为什么我会出现分段错误 2)如何解决在List()中创建的每个项目都有一个单独的地址?

问题

在列表构造函数中,将对象item的地址放入列表中,该对象是循环的本地对象,并在每次迭代结束时销毁。

解决方案

您必须在免费存储区中创建一个new对象,以便它在迭代和构造函数结束时幸存下来。 在你学习的过程中,我保持简单并使用原始指针:

List(int size) {
for (int i = 0; i < size; i++) {
Item *pitem = new Item;  
pitem->data = i;  
if (i == 0) 
start = pitem;
if (i > 0)
buffer->next = pitem;
//Storing current address in buffer
buffer = pitem;
//Outputting address and value (just for testing purposes)
//std::cout << "Address: " << pitem << " -> " << item->data << std::endl;
}
}

但是这样你的代码就会泄漏内存。 如果你有这样的构造函数,你还需要一个复制构造函数、一个赋值运算符和一个析构函数(规则 3)

Item item;

是一个堆栈分配变量,这意味着当程序退出当前范围(在本例中为循环迭代)时,它将被解除分配。内存地址是相同的,因为编译器每次都在同一位置分配内存地址。程序崩溃,因为您尝试取消引用指向任何内容的指针。

您应该通过new Item;动态分配堆上的每个Item- 但要小心,您必须对分配的每个变量调用delete,否则您自己就会出现内存泄漏。