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

查看:392
本文介绍了在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)中声明的项的地址存储在缓冲区中,以便可以将在迭代n中的项的地址设置为上一次迭代(n-1)中的项的下一个. 这样可以将所有项目彼此链接.

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

但是,当我取消第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->数据会导致分段错误!

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; DR 1)为什么会出现细分错误 2)如何解决在List()中创建的每个项目都有单独的地址?

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天全站免登陆