Is this function that returns by reference safe?
Jan 2, 2021 at 7:26am UTC
Hello. I never really learned how to return by reference in C++
but I was making a linked list class and I want to make a function:
T& operator[int index] and I'd guess I need to return a reference
to the node with the given index. So, is this code a safe way to do
that?
1 2 3 4 5 6 7 8 9 10 11 12 13 14
T& operator [](int index)
{
Node<T>* temp = head;
int i = 0;
while (temp != nullptr )
{
if (i == index)
return temp;
temp = temp->next;
i++;
}
}
I would guess it not to be safe since 'temp' goes out
of scope... Correct?
EDIT: Will this code cause undefined behavior?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
#include <iostream>
#include <string>
template <typename T>
class Node
{
public :
T data;
Node* next;
};
template <typename T>
class List
{
public :
~List()
{
Node<T>* current = head;
while (current != 0) {
Node<T>* next = current->next;
delete current;
current = next;
}
head = 0;
}
List() noexcept = default ;
void Add(T value)
{
Node<T>* newNode = new Node<T>{ value, nullptr };
if (head == nullptr ) head = newNode;
else
{
Node<T>* temp = head;
while (temp->next != nullptr ) temp = temp->next;
temp->next = newNode;
}
}
T& operator [](int index)
{
Node<T>* temp = head;
int i = 0;
while (temp != nullptr )
{
if (i == index)
return temp->data;
temp = temp->next;
i++;
}
}
int Count()
{
int _count = 0;
Node<T>* temp = head;
while (temp != nullptr )
{
_count++;
temp = temp->next;
}
return _count;
}
void Display() const noexcept
{
Node<T>* temp = head;
while (temp != nullptr )
{
std::cout << temp->data;
std::cout << ' ' ;
temp = temp->next;
}
std::cout << '\n' ;
}
private :
Node<T>* head = nullptr ;
};
int main()
{
List<std::string> list;
list.Add("A" );
list.Add("B" );
list.Add("C" );
list.Display();
std::cout << list.Count();
std::cout << list[0]; // This is the line I think might cause problems.
return 0;
}
Last edited on Jan 2, 2021 at 8:12am UTC
Jan 2, 2021 at 9:07am UTC
This also makes it unsafe.
1 2
In member function 'T& List<T>::operator[](int) [with T = std::basic_string<char>]' :
58:5: warning: control reaches end of non-void function [-Wreturn-type]
If the subscript isn't in range, then perhaps
https://www.cplusplus.com/reference/stdexcept/out_of_range/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
T& operator [](int index)
{
Node<T>* temp = head;
int i = 0;
while (temp != nullptr )
{
if (i == index)
return temp->data;
temp = temp->next;
i++;
}
throw std::out_of_range("oops" );
}
Jan 2, 2021 at 11:32am UTC
The code can be somewhat simplified. Consider:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
#include <iostream>
#include <string>
template <typename T>
class Node
{
public :
T data {};
Node* next {};
};
template <typename T>
class List
{
public :
~List() noexcept
{
while (head != nullptr ) {
const auto next {head->next};
delete head;
head = next;
}
}
List() noexcept = default ;
void Add(T value)
{
const auto newNode {new Node<T> {value, nullptr }};
if (head == nullptr )
head = newNode;
else
{
auto temp {head};
for (; temp->next != nullptr ; temp = temp->next);
temp->next = newNode; }
}
T& operator [](size_t index)
{
auto temp {head};
for (size_t i {}; temp != nullptr ; temp = temp->next, ++i)
if (i == index)
return temp->data;
throw std::out_of_range("Bad index" );
}
size_t Count() const noexcept
{
size_t _count {};
for (auto temp = head; temp != nullptr ; temp = temp->next, ++_count);
return _count;
}
void Display() const noexcept
{
for (auto temp = head; temp != nullptr ; temp = temp->next)
std::cout << temp->data << ' ' ;
std::cout << '\n' ;
}
private :
Node<T>* head {};
};
int main()
{
List<std::string> list;
list.Add("A" );
list.Add("B" );
list.Add("C" );
list.Display();
std::cout << list.Count() << '\n' ;
std::cout << list[0] << '\n' ;
try {
std::cout << list[4] << '\n' ;
}
catch (const std::out_of_range& ex) {
std::cout << ex.what() << '\n' ;
}
}
Last edited on Jan 2, 2021 at 11:44am UTC
Topic archived. No new replies allowed.