#include <iostream>
#include<cstddef>
#include<string>
using namespace std;
class spexception
{
protected:
string description;
public:
spexception();
spexception(const string&);
virtual const string& what();
};
template <class T>
class sp
{
private:
T* p;
sp(T*);
public:
sp();
sp(const T&);
sp(int);
T& operator * ();
T* operator -> ();
sp& operator = (const sp&);
sp& operator = (const T&);
sp& operator = (int);
bool operator == (const sp&);
~sp();
};
spexception::spexception() : description("No description.")
{}
spexception::spexception(const string& s) : description(s)
{}
const string& spexception::what()
{
return description;
}
template<class T>
sp<T>::sp()
{
p = NULL;
}
template<class T>
sp<T>::~sp()
{
if(p!=NULL) delete p;
}
template<class T>
sp<T>::sp(const T& t)
{
p = new T(t);
}
template<class T>
sp<T>::sp(int i)
{
if(i!=0) throw spexception("Smart pointer cannot be initialized from a non-zero integer.");
p = NULL;
}
template<class T>
sp<T>& sp<T>::operator = (const sp& q)
{
if(*this==q) return *this;
if(p!=NULL) delete p;
p = q.p;
return *this;
}
template<class T>
sp<T>& sp<T>::operator = (const T& t)
{
p = new T(t);
}
template<class T>
sp<T>& sp<T>::operator = (int i)
{
if(i!=0) throw spexception();
p = NULL;
}
template<class T>
bool sp<T>::operator == (const sp& q)
{
return(p==q.p);
}
template<class T>
T& sp<T>::operator * ()
{
return *p;
}
template<class T>
T* sp<T>::operator -> ()
{
return p;
}
using namespace std;
class node
{
public:
int val;
sp<node> next;
node()
{
val = 5;
}
node(int v) : val(v)
{
cout<<"\nNode with value "<<val<<" created.\n";
}
~node()
{
cout<<"\nNode with value "<<val<<"destroyed.\n";
}
};
class list
{
sp<node> first;
sp<node> last;
public:
list()
{
first = NULL;
last = NULL;
}
void add(int v)
{
if(last==NULL)
{
last = node(v);
first = last;
//last->next = NULL;
}
else
{
last->next = node(v);
//last->next->next = NULL;
last = last->next;
}
}
};
main()
{
list l;
l.add(10);
l.add(20);
l.add(30);
l.add(40);
}
The output is "Node with value 40 destroyed" printed infinite times. According to gdb debugger, the problem happens in the list destructor. According to the gd debugger, there is some node which has a smart pointer pointing to the same node. So when the destructor is called it is supposedly being called infinite times. But I dont see this happening in the code. What exactly is the problem?
EDIT: As molbdnilo pointed out, when the destructor for the 'last'smart pointer is called, an attempt is made to delete a dangling pointer. This should cause a crash. However the program is going into an infinite loop instead. Is this a bug with mingw compiler?
template<class T>
sp<T>& sp<T>::operator = (const sp& q)
{
if(*this==q) return *this;
if(p!=NULL) delete p;
p = q.p;
return *this;
}
In the Above Function The Pointer 'p' gets deleted and next instruction tries to assign a value 'q.p' to the deleted 'p',which can cause problem.
I made changes to above function as given below.
template<class T>
sp<T>& sp<T>::operator = (const sp& q)
{
if(*this==q) return *this;
if(p!=NULL) p = q.p;
return *this;
}
This worked out well.
You have no copy constructor, so the default copy constructor will just copy the pointer, giving you two smart pointer objects that point at the same object.
Similarly, you assignment operator just copies the pointer, giving you two smart pointer objects that point at the same object.
Whenever either of these happens, the destructor for the first smart pointer will delete the object, leaving the other smart pointer dangling. When the second smart pointer is destroyed, it deletes the already deleted pointer again, causing undefined behavior.
When you copy or assign a smart pointer, you need to either also clone the pointed at object, or have a reference count somewhere that tracks how many pointers point at the same object. In this latter case, you only delete the object when the refcount drops to 0.
Related
So i have a Linked list implementation of my own and it can successfully keep integers and call them when needed with overloaded [] operator but when it comes to storing a class in my linked list, it seems that i can't call the class appropriately (using the same [] operator).
Called functions and members of my Linked List;
#include <iostream>
#include <assert.h>
template<typename T>
struct node {
T data;
node<T>* next;
};
template<typename T>
class Vectem {
private:
node<T>* head;
node<T>* last;
int lenght;
public:
void insert(T value) {
last->next = new node<T>;
last = last->next;
last->data = value;
last->next = NULL;
if (isEmpty()) {
head = last;
}
lenght++;
}
node<T>* search(int indx) {
node<T>* current;
current = head;
int count=0;
while (current != NULL) {
if (count == indx) {
break;
}
current = current->next;
count++;
}
return current;
}
T& operator [](int indx) {
assert(indx >= lenght - 1);
T result;
result = search(indx)->data;
return result;
}
};
And here is the main function and the class that i try to store;
#include <iostream>
#include <fstream>
#include <string>
#include "VectemLibrary.h"
class word {
public:
std::string value;
int count;
word(std::string value, int count): value(value),count(count) {
}
word() {
value = "NOT ASSIGNED";
count = 0;
}
word(const word& w1) {
value = w1.value;
count = w1.count;
}
~word() {
std::cout << "Word Destroyed" << std::endl;
}
};
int main()
{
Vectem<word> wordContainer;
word newWord("hello", 1);
wordContainer.insert(newWord);
std::cout << wordContainer[0].value;
}
Visual studio gave me the expection with this message at the last line where i call the first member of linked list with [];
Exception thrown at 0x7A0CF3BE (ucrtbased.dll) in Top 10 words.exe: 0xC0000005: Access violation reading location 0xCCCCCCCC.
I think that my lack of experience with pointers may have caused the problem but if you see something that i can't, Please enlighten me.
There are other problems with the code you posted as well (e.g. isEmpty() is not declared or defined), but I'll focus on the issue you explicitly mentioned.
In your operator:
T& operator [](int indx) {
assert(indx >= lenght - 1);
// You declare this variable on the stack
T result;
result = search(indx)->data;
// And then you return this variable by reference; this is not okay
return result;
}
As mentioned in my code comments (and by #Johnny Mopp in his comment to your post), you shouldn't (can't) return a reference or pointer to a variable declared within the returning function and constructed on the stack. Anything on the stack will be destroyed once the function call ends, so any returned pointers or references to such variables will be dangling references; using said pointers or references will result in undefined behavior.
So you don't want to return a reference to a stack-allocated variable like result; you want to return a reference to the data within the node itself (which is allocated on the heap by insert()), as it will still be a valid reference after the function returns:
return search(indx)->data;
There are several problems with your code, but the most important is that you are not initializing the head, last, or lenght members of Vectem at all. An Access Violation error at address 0xCCCCCCCC is a good indication that uninitialized memory is being accessed, as some compilers/setups fill uninitialized memory with 0xCC bytes, thus head and last are initially 0xCCCCCCCC in your case.
You need to add appropriate constructors to Vectem (as well as a destructor, a copy constructor, and a copy assignment operator, per the Rule of 3), eg:
template<typename T>
class Vectem {
private:
node<T>* head;
node<T>* last;
int lenght;
public:
Vectem() : head(NULL), last(NULL), lenght(0) {}
Vectem(const Vectem &src) : head(NULL), last(NULL), lenght(0)
{
// copy src's data to *this as needed ...
}
~Vectem()
{
// cleanup *this as needed ...
}
Vectem& operator=(const Vectem &rhs)
{
if (&rhs != this) {
// clear *this, and copy rhs's data to *this, as needed ...
}
return *this;
}
...
};
Or, in C++11 and later, you can initialize the members directly in their declarations (also, be sure to add a move constructor and a move assignment operator, per the Rule of 5), eg:
template<typename T>
class Vectem {
private:
node<T>* head = nullptr;
node<T>* last = nullptr;
int lenght = 0;
public:
Vectem() = default;
Vectem(const Vectem &src)
{
// copy src's data to *this as needed ...
}
Vectem(Vectem &&src) : head(src.head), last(src.last), lenght(src.lenght)
{
src.head = nullptr;
src.last = nullptr;
src.lenght = 0;
}
~Vectem()
{
// cleanup *this as needed ...
}
Vectem& operator=(const Vectem &rhs)
{
if (&rhs != this) {
// clear *this, and copy rhs's data to *this, as needed ...
}
return *this;
}
Vectem& operator=(Vectem &&rhs)
{
// clear *this as needed...
head = rhs.head; rhs.head = nullptr;
last = rhs.last; rhs.last = nullptr;
lenght = rhs.lenght; rhs.lenght = 0;
return *this;
}
...
};
That being said, insert() is also buggy, as it is dereferencing last before checking that last is actually pointing at a valid node. Try something more like this instead:
void insert(T value) {
node<T> *n = new node<T>{value, NULL};
if (!head) head = n;
if (last) last->next = n;
last = n;
++lenght;
}
Alternatively:
void insert(T value) {
node<T> **p = (last) ? &(last->next) : &head;
*p = new node<T>{value, NULL};
last = *p;
++lenght;
}
So I've got this code:
//movable_ptr.hpp
//Michal Cermak
template<typename T> class movable_ptr;
template<typename T> class enable_movable_ptr {
public:
//default constructor
enable_movable_ptr() {};
//move constructor and assignment
enable_movable_ptr(enable_movable_ptr<T>&& p) {
first_ = p.getFirst();
p.retarget_to(this);
};
enable_movable_ptr<T>& operator=(enable_movable_ptr<T>&& p) {
if (this != &p)
{
first_ = p.getFirst();
p.retarget_to(this);
delete &p;
}
return *this;
};
//retargets all pointers in the linked list to a new address
void retarget_to(T* p)
{
if (first_ != nullptr)
{
auto current = first_;
do
{
current->set(p);
current = current->getNext();
} while (current != first_);
}
};
movable_ptr<T>* getFirst() { return first_; };
void setFirst(movable_ptr<T>* p) { first_ = p; };
private:
movable_ptr<T>* first_ = nullptr;
};
template<typename T> class movable_ptr {
public:
//constructors and stuff...
//access to variables
T* get() {return ptr_; };
void set(T* p) { ptr_ = p; };
movable_ptr<T>* getNext() { return next_; };
void setNext(movable_ptr<T>* p) { next_ = p; };
movable_ptr<T>* getPrevious() {return prev_; };
void setPrevious(movable_ptr<T>* p) { prev_ = p; };
private:
T* ptr_ = nullptr;
movable_ptr<T>* next_ = this;
movable_ptr<T>* prev_ = this;
};
My problem is that I need to give T * to retarget_to, but I use retarget_to(this) in the move constructor and assignment in enable_movable_ptr. That passes it enable_movable_ptr<T> * instead of just T *. The thing is, I assume that T inherits from enable_movable_ptr, which will never be used directly, only through the object that inherits from it. For example:
class A : public enable_movable_ptr<A>
{
public:
int val;
A(int val) : val(val) {}
};
And then used like this:
A x(42);
A y = move(x);
In this case, this would be enable_movable_ptr<A> *, but I need something that would give me A * instead. Basically I need a pointer to the lvalue of the = operator, while inside an overload of said operator. Is there any way to do this or am I asking for something impossible?
I haven't understood your question entirely, because it's not clear what you want to achieve with this enable_movable_ptr class. I think your way of writing operator= is ill-formed. You are trying to explicitly call delete on a pointer to r-value (which may firstly be allocated on stack, and moreover probably will be destroyed later anyway via some other mechanism).
I would suggest to consider copy-and-swap approach for operator=, this would allow you to not worry about checking if you are assigning object into itself. The signature would be enable_movable_ptr<T>& operator=(enable_movable_ptr<T> other) (note passing by value).
I'm trying to create a class template for a link-list implementation of a Stack. Now I've gotten the push, pop, peek, and tested the destructor. But I'm wondering how should I add the copy constructor, overloaded assignment operator, and the deepCopy on my code. Here is what I got so far:
// Lab3.cpp
//
// Created by IvanChak on 4/3/16.
// Copyright © 2016 Space. All rights reserved.
#include <iostream>
using namespace std;
template<class T>
struct Node {
T item;
Node* next = NULL;
Node(T t = {}, Node* link = nullptr) :item{t}, next{link} { }
~Node() { delete next; }
};
template<class T>
class Stack {
public:
bool empty() const { return n == 0; }
void push(const T&);
T pop();
T peek();
~Stack();
private:
Node<T>* top = NULL;
size_t n;
};
template <class T>
class A
{
public:
A(const A &){}
A & operator=(const A& a){return *this;}
};
template<class T>
Stack<T>::~Stack() {
cout<<"Destructor, deallocate..."<<endl;
}
template<class T>
void Stack<T>::push(const T& t) {
Node<T>* previous{top};
top = new Node<T>{t,previous};
++n;
}
template<class T>
T Stack<T>::pop() {
if (empty()) {
cout << "Empty" << endl;
}
Node<T>* oldnode = top;
T t = top->item;
top = top->next;
--n;
delete oldnode;
return t;
}
template<class T>
T Stack<T>::peek() {
if (empty()) {
cout << "Empty" << endl;
}
return top->item;
}
int main(int argc, const char * argv[]) {
Stack<string> x{};
x.push("Hello");
x.push("Second");
x.push("Bye");
cout << x.peek() << endl;
x.pop();
cout << x.peek() << endl;
}
I don't know if you still need an answer or not, but if you do, you would want something like this for you copy constructor and your assignment operator:
template<class T>
Stack<T>::Stack(const Stack<T>& rhs)
{
if (rhs.top)
{
this->top = new Node<T>(rhs.top->item);
Node<T>* rhsNode = rhs.top; // This pointer is used for iterating through the "rhs" argument.
Node<T>* currentNode = this->top; // This pointer is used for iterating through "this".
n = 1;
while (rhsNode->next) // Loop untill the end of the stack has been reached.
{
++n;
currentNode->next = new Node<T>(rhsNode->next->item);
currentNode = currentNode->next;
rhsNode = rhsNode->next;
}
}
else // "rhs" is empty
{
n = 0;
this->top = nullptr;
}
}
Note: I wrote this code in a "deep copy" fashion. I can't think of any situation where it would be good to do a "shallow copy" on this type of data structure; in fact, I think it would be a very bad idea to do so. I don't automatically assume that you are planning on making your copy constructor do a "shallow copy" on your stack, but since you named the copy constructor and something about "deep copying" separately, I see it as entirely possible that you are.
I tested this code, and it worked.
I am creating a class LinkedList. I am having difficulty adding another node to my list.
Here is what I have so far:
template<typename T>
class LinkedList
{
private:
T element;
T *next;
public:
LinkedList();
LinkedList(T element);
void add(LinkedList<T> &otherList);
void print();
};
template<typename T>
LinkedList<T>::LinkedList()
{
next = NULL;
}
template<typename T>
LinkedList<T>::LinkedList(T element)
{
this->element = element;
next = NULL;
}
template<typename T>
void LinkedList<T>::add(LinkedList<T> &otherList)
{
next = &otherList;
}
template<typename T>
void LinkedList<T>::print()
{
LinkedList<T> *current = this;
while (current != NULL)
{
std::cout << current->element;
current = current->next;
}
}
int main()
{
LinkedList<std::string> myFirst("First");
LinkedList<std::string> mySecond("Second");
myFirst.add(mySecond);
myFirst.print();
return 0;
}
This works however if I make the change:
void add(const LinkedList<T> &otherList);
template<typename T>
void LinkedList<T>::add(const LinkedList<T> &otherList)
{
next = &otherList; //now an error right here
}
Then I get an error stating:
Assigning to 'LinkedList<std::__1::basic_string<char> > *' from incompatible type 'const LinkedList<std::__1::basic_string<char> > *'
Why is it I get this error?
next is a T*, and you're trying to assign a const LinkedList<T>* to it.
I suppose you meant something like next = &(otherList.element) (though even then I think your list semantics are somewhat broken — elements shouldn't typically be shared by multiple containers unless you're very, very clear about the ownership semantics).
Contrary to your claims, your first program doesn't work either for the same reason.
Please tell me how the operator->() in being defined for the iterator of std::list in order to refer members of the element that is being pointed by an iterator.
EDIT:
The problem is that if you implement like this (Fred Nurk):
template<class T>
struct list {
private:
struct Node { // internal class that actually makes up the list structure
Node *prev, *next;
T data;
};
public:
struct iterator { // iterator interface to the above internal node type
T* operator->() const {
return &_node->data;
}
private:
Node *_node;
}
};
Then when you write:
struct A {
int n;
};
void f() {
list<A> L; // imagine this is filled with some data
list<A>::iterator x = L.begin();
x->n = 42;
}
Then
x->n I understand like x->operator->()n which is equivalent to (A ponter to a)n which is a nonsence. How to understand this part. Some answers tell that it is equivalent to x->operator->()->n; (instead of x->operator->()n) but I don't understand why. Please explain me this.
(hint: It returns a pointer to the element.)
The -> operator behaves as follows:
T->x; // some field
T->foo(); // some function
...is equivalent to:
T.operator->()->x;
T.operator->()->foo();
Note the re-application of -> to whatever is returned.
With many details elided, here is the gist of how it works:
template<class T>
struct list {
private:
struct Node { // internal class that actually makes up the list structure
Node *prev, *next;
T data;
};
public:
struct iterator { // iterator interface to the above internal node type
T* operator->() const {
return &_node->data;
}
private:
Node *_node;
}
};
Thus, given:
struct A {
int n;
};
void f() {
list<A> L; // imagine this is filled with some data
list<A>::iterator x = L.begin();
x->n = 42;
// x.operator->() returns an A*
// which gets -> applied again with "n"
}
Operator -> is implemented differently than the other operators in C++. The operator function is expected to return a pointer, and the -> is applied again to that pointer.
It returns pointer. Just for completeness, here is simple example:
#include <iostream>
#include <vector>
using namespace std;
template <typename T>
class SafeVectorIterator
{
vector<T> & _vec;
size_t _pos;
public:
SafeVectorIterator(vector<T> & vec) : _vec(vec), _pos(0) { }
void operator++() { ++_pos; }
void operator--() { --_pos; }
T& operator*() { return _vec.at(_pos); }
T* operator->() { return &_vec.at(_pos); }
};
struct point { int x, y; };
int main()
{
vector<point> vec;
point p = { 1, 2 };
vec.push_back(p);
vec.push_back(p);
SafeVectorIterator<point> it(vec);
++it;
it->x = 8;
cout << (*it).y << '\n';
return 0;
}