2016-03-03 2 views
4

Для того, чтобы завершить свою домашнюю работу я должен был реализовать список в C++, таким образом, я определил структуру:указатели на структуры в C++

struct Node { 
    int value; 
    Node * next; 
    Node * operator [] (int index)//to get the indexed node like in an array 
    { 
     Node *current = this; 
     for (int i = 0; i<index; i++) 
     { 
      if (current==NULL) return NULL; 
      current = current->next; 
     } 
     return current; 
    } 
}; 

Когда я использовал его с реальными структурами, он работал отлично:

Node v1, v2, v3; 
v1.next = &v2; 
v2.next = &v3; 
v3.value = 4; 
v3.next = NULL; 
cout<<v1[2]->value<<endl;//4 
cout<<v2[1]->value<<endl;//4 
cout<<v3[0]->value<<endl;//4; works just as planned 
cout<<v3[1]->value<<endl;//Segmentation fault 

Но когда я пытался использовать его с указателями, вещи получил перепутались:

Node *v4, *v5, *v6; 
v4 = new Node; 
v5 = new Node; 
v6 = new Node; 
v4->next = v5; 
v4->value = 44; 
v5->next = v6; 
v5->value = 45; 
v6->next = NULL; 
v6->value = 4646; 
//cout cout<<v4[0]->value<<endl; compiler says it's not a pointer 
cout<<v4[0].value<<endl;//44 
cout<<v4[1].value<<endl;//1851014134 
cout<<v4[2].value<<endl;//45 
cout<<v4[3].value<<endl;//1851014134 
cout<<v4[4].value<<endl;//4646 
cout<<v4[5].value<<endl;//1985297391;no segmentation fault 
cout<<v6[1].value<<endl;//1985297391;no segmentation fault even though the next was NULL 
delete v4; 
delete v5; 
delete v6; 

Хотя можно работа с функцией, у меня есть вопросы:

  1. Почему возвращаемое значение в примере указателей было структурой, но не указателем?
  2. Почему элементы теперь имеют двойной индекс и какие элементы между ними?
  3. Почему не произошла ошибка сегментации?

Я был бы очень благодарен, если кто-то объяснил мне эти моменты или дал мне источники, я мог бы извлечь из

+0

Во втором фрагменте кода вы четко должны UB, как вы использовали '' v1'and v2' член 'value' без его инициализации. Я предлагаю добавить конструктор по умолчанию, чтобы поставить это значение в '0' –

ответ

5

Это потому, что v4[0] (и остальные) на самом деле не звонит Node::operator[]. Это потому, что v4 не является Node, это Node*, а указатели имеют встроенное значение позади operator[]: v4[i] == *(v4 + i) (т. Е. Мы просто индексируем этот «массив»). Поэтому, когда вы пишете что-то вроде v4[3], то есть не звоните operator[](3) ... вместо этого вы возвращаете Node три Node s после v4 в памяти где-то, что в основном просто мусор.

Чтобы получить то, что вы хотите, чтобы это произошло, вы должны разыменования указателей первых:

(*v4)[0] 
(*v6)[1] 
// etc 
+0

Спасибо за ответ! Это объясняет все, что я не знал о встроенном операторе . Означает ли это, что у меня нет способа изменить оператора, что он будет работать, как я и хотел? – undocreado

+0

@undocreado Вы должны просто не иметь оператора. Не имеет смысла предоставлять 'operator []' для связанного списка. – Barry

+0

Я хотел иметь его, потому что он будет делать такие методы, как elementAt, deleteAt или insert, легче писать, поскольку я просто получу проиндексированный элемент моего первого узла списка. Лучше ли просто выполнять какую-либо функцию или писать код для этого в каждом методе? – undocreado

1

Делая это

v4 = new Node; 
cout<<v4[0].value<<endl;//44 
cout<<v4[1].value<<endl;//1851014134 
cout<<v4[2].value<<endl;//45 
cout<<v4[3].value<<endl;//1851014134 
cout<<v4[4].value<<endl;//4646 
cout<<v4[5].value<<endl;//1985297391;no segmentation fault 

Вы не вызывая оператор [] из структуры узла, вы делаете разыменование указателя, v4[1] равно ++v4; *v4; Так что этот код вызывает непредсказуемое поведение, потому что вы разыскиваете какой-то мусор. Чтобы заставить его работать, как вы хотите, вы должны изменить его на:

cout<<v4->operator[](0).value<<endl; 
cout<<v4->operator[](1).value<<endl; 
cout<<v4->operator[](2).value<<endl; 
... 
+0

Благодарим за ответ! Это сработало – undocreado

Смежные вопросы