在 for 循环中创建的对象具有相同的地址 [英] Object created in for-loop has same address

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

问题描述

我正在尝试创建一个自己的列表类,它具有固定大小并且可以存储整数.仅用于学习目的.

I'm trying to make an own list-class which is of a fixed size and can store integers. Just for learning purposes.

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

This is how I do it: I have a struct called Item which holds the data (the integer to store), and a pointer to the next item in the list. When the list gets initialized I first add x amount of empty Items to the list.

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

The address of item declared in iteration (n-1) is stored in a buffer, so that the address of the item in iteration n, can be set as next for the item in the previous iteration (n-1). This to chain all items to each other.

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

And the address of the very first item is also saved, as the access point for the whole list later in the code.

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

But it's not really working; this is my code:

#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

但是,当我取消注释 testing-line 37 时,输出如下:

However, when I uncomment testing-line 37 this is the output:

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

Testing output:
1648675776
1648572376
1646105840
1226279756
Segmentation fault

我一开始不明白输出如何如此剧烈地改变测试输出"的输出......

I don't understand in the first place how outputting can change the output of 'Testing output' this drastically...

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

Anyway, segmentation fault info:

(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;

不知道为什么 current->data 会出现分段错误,因为我给每个元素都提供了数据!

No idea why current->data gives the segmentation fault, as I gave data to each element!

但最困扰我的是:

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

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

Each item has the same address, of course, this isn't what I meant. Each item created in the iterations should be another item with another address. Has this something to do with Item being declared local, and the object for that reason is stored on the stack and not in free space? I tried using the 'new' keyword, but that didn't work!

TL;DR1)为什么我得到分段错误2) 如何解决 List() 中创建的每个 Item 都有一个单独的地址?

TL;DR 1) Why am I getting the segmentation fault 2) How to fix that each Item created in List() has a separate address?

推荐答案

问题

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

In your list constructor, you put in your list the address of an object item that is local to the loop and gets destroyed at the end of each iteration.

解决方案

您必须在自由存储中创建一个 new 对象,这样它才能在迭代和构造函数结束时继续存在.在您学习的过程中,我保持简单并使用原始指针:

You have to create a new object in the free store, so that it survives the iteration and the end of the constructor. As you're learning, i keep it simple and use raw pointers:

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)

But then your code will leak memory. If you have such a constructor, you'll also need a copy constructor, an assignment operator and a destructor (rule of 3)

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

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