从指针数组中的地址索引?

时间:2017-06-14 14:09:51

标签: c++ arrays pointers

以下代码的解决方案:

  

“在不更改函数提供的用户界面的情况下,从§27.9更改LinkList的表示形式。在Link数组中分配Links并拥有成员:firstlastprevnextint s(数组中的索引)。“ - 练习6章27 - 编程:使用C ++的原理和实践B. Stroustrup

该接口继承自 Intrusive 双向链表的普通实现。我添加了bool数组(以及相关的函数)来跟踪内存:

 #include <iostream>

struct Link
{
    int next;
    int prev;
};

//------------------------------------------------------------------------------------

struct List
{
    Link** head;
    int first;      // points to the current first node
    int last;

    bool* available;
    int list_size;

    int get_index()
    {
        for (int i = 0; i < list_size; ++i)
        {
            if (available[i] == true) 
            {
                available[i] = false;
                return i;
            }
        }
        throw std::bad_alloc("bla bla!\n");
    }

    List()
    {
        list_size = 30;

        head = new Link*[list_size];
        available = new bool[list_size];

        first = -1;
        last = -1;

        for (int i = 0; i < list_size; ++i)
        {
            available[i] = true;
        }
    }

    void List::push_back(Link* l)
    {
        if (l == nullptr)
        {
            throw std::invalid_argument("bla bla!\n");
        }

        int index = get_index();
        head[index] = l;

        if (last != -1)
        {
            head[last]->next = index;
            head[index]->prev = last;
        }
        else
        {
           first = index;
           head[index]->prev = -1;
        }

        last = index;
        head[index]->next = -1;
    }

    void push_front(Link* l)
    {
        if (l == nullptr)
        {
            throw std::invalid_argument("bla bla\n");
        }

        int index = get_index();
        head[index] = l;

        if (first != -1)
        {
            head[first]->prev = index;
            head[index]->next = first;
        }
        else
        {
            last = index;
            head[index]->next = -1;
        }

        first = index;
        head[index]->prev = -1;
    }

    // index = ptr - base
    std::ptrdiff_t index_from_address(Link* l) { return l - head[0]; }

    Link* front() const { return head[first]; }
};

//------------------------------------------------------------------------------------

int main()
{
    List l;

    for (int i = 0; i < 10; ++i)
    {
        l.push_back(new Link());
    }

    for (int i = 0; i < 10; ++i)
    {
        l.push_front(new Link());
    }

    std::cout <<"first = "<< l.first <<", index = " << l.index_from_address(l.front());
    getchar();
}

预期结果:

  

first = 19, index = 19

实际结果:

  

first = 19, index = 194

为什么呢?

1 个答案:

答案 0 :(得分:3)

l - head[0]

在这里,您可以比较两个指针的。您可以让数组中的所有指针都默认初始化,因此它们的值是不确定的,因此访问值的行为是未定义的。

您可能希望index_from_address找到存储特定指针对象的索引 - 而不是指向的对象,因为指向的对象不在指向的数组中按head。为此,您必须添加一大堆&

 Link*& front() const // return a reference to the pointer object, not a copy

 //  take a reference to the pointer as an argument, add const for good measure
 std::ptrdiff_t index_from_address(Link*& l) const
// compare the addresses of the pointers, rather than values
 { return &l - &head[0]; }