以下代码的解决方案:
“在不更改函数提供的用户界面的情况下,从§27.9更改
Link
和List
的表示形式。在Link
数组中分配Links
并拥有成员:first
,last
,prev
和next
为int
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
为什么呢?
答案 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]; }