Linked-List only remembers most recent added object - c++

I have an assignment that requires me to add objects into a linked list. The objects in question are Shapes.
My problem is that I can add objects to the list, but when I try to print them out, only the last added object is printed, the rest are just trash values.
My code looks like this:
Source.cpp:
#include "ShapeList.h"
#include <iostream>
using namespace std;
int main()
{
ShapeList list;
list.add(Rectangle(0,0,2,5));
list.print();
}
I am not allowed to change this code. For example, I am not allowed to send a pointer to the new rectangle, I'm supposed to "deep-copy" it. (I hope I'm using that word right.)
My ShapeList.h looks like this:
#ifndef SHAPELIST_H
#define SHAPELIST_H
#include "Shape.h"
#include "Rectangle.h"
class ShapeList
{
private:
Shape *conductor; //this will point to each node as it traverses the list
Shape *root; //the unchanging first node
public:
ShapeList();
void print();
void add(const Shape &s);
};
#endif
and the header looks like:
#include "ShapeList.h"
#include <iostream>
using namespace std;
ShapeList::ShapeList()
{
cout << "ShapeList created" << endl;
root = new Shape; //now root points to a node class
root->next = 0; //the node root points to has its next pointer set to equal a null pointer
conductor = root; //the conductor points to the first node
}
void ShapeList::add(const Shape &s)
{
cout << "Shapelist's add function called" << endl;
conductor->next = new Shape; //creates node at the end of the list
conductor = conductor->next; //goes to next node
Shape *pShape = s.clone(); //get a pointer to s
conductor->current = pShape; //points current to pShape point
conductor->next = 0; //prevents loops from going out of bounds
}
void ShapeList::print()
{
conductor = root; //the conductor points to the start of the linked list
if(conductor != 0)
{
while(conductor->next != 0)
{
conductor = conductor->next;
cout << conductor->current->width << endl;
}
//cout << conductor->current->width << endl;
}
}
The clone-function is overloaded in all shapes, in this case it's the rectangle's:
Rectangle * Rectangle::clone() const
{
cout << "Rectangle's clone function called" << endl;
Rectangle copiedRect(this);
Rectangle * pCopiedRect = &copiedRect;
return pCopiedRect;
}
Rectangle::Rectangle(const Rectangle *ref)
{
cout << "Rectangle's copy constructor called" << endl;
this->x = ref->x;
this->y = ref->y;
this->width = ref->width;
this->height = ref->height;
}
I know it's alot to read, and I'm sorry. I can remove stuff if it's not needed. I can also add more if you would like.
I have read Alex Allain's tutorial* about linked lists, and a couple of other articles. If anyone has another article, or something like that, to suggest I'm all ears.
http://www.cprogramming.com/tutorial/c/lesson15.html

Rectangle::clone() is invoking undefined behavior. You're returning the address of an automatic variable copiedRect, which falls of scope as soon as the function terminates.
Try this:
Rectangle * Rectangle::clone() const
{
cout << "Rectangle's clone function called" << endl;
return new Rectangle(*this);
}
And your copy-ctor should not even need to be implemented. All the members of Rectangle are trivially copyable. The default should work fine.
Note: I didn't really take the time to dissect your list insertion code, but the above is definitely a problem that needs to be addressed.

Related

Why is the constructor of the class called four times, and the destructor is only called twice when the program is about to end?

Why is the constructor of the class called four times, and the destructor is only called twice when the program is about to end?
I want to construct a one-way circular linked list and it's OK, but I got some problems on the destructor of the Bufferclass.
The code is as follows:
#include <iostream>
#include <string>
#include <memory>
using namespace std;
class Buffer
{
public:
Buffer(): Next(nullptr)
{
int id = ID + 1;
ID++;
std::cout << "Thi is the " << id << "th buffer." << endl;
}
~Buffer()
{
cout << "The buffer is destructed." << endl;
}
shared_ptr<Buffer> Next;
static int ID;
};
int Buffer::ID = 0;
int main()
{
int LogBufferNum = 4;
shared_ptr<Buffer> Head = std::make_shared<Buffer>();
Head->Next = Head;
LogBufferNum--;
while (LogBufferNum > 0)
{
std::shared_ptr<Buffer> New = std::make_shared<Buffer>();
std::shared_ptr<Buffer> Temp(Head);
New->Next = Head;
Temp->Next = New;
Temp = New;
LogBufferNum--;
}
return 0;
}
it prints as:
The is the 1th buffer.
The is the 2th buffer.
The is the 3th buffer.
The buffer is destructed.
The is the 4th buffer.
The buffer is destructed.
Any solutions? Thank you very much
When you create a circular reference with shared_ptr, i.e. A contains a pointer to B and B contains a pointer to A, those object will never be destroyed. In this case two of your Buffers are pointing to each other. Try working out on paper what you are doing when you set up those pointers and you will see the circular reference.

Vector attributes on class instance in returned pointer attribute disappearing

I'm implementing a kind of tree search that requires being able to get a "most promising node" from a tree and then doing something with that node in order to update the remainder of the tree for the next iteration.
Problem: an object pointer Board* has vector attributes that seem to change between the return of the function producing them, and the Board* value holding them in the calling environment.
My output:
>>g++ -std=c++17 -o tmp.out tests/test.cpp // <- require c++17 for other parts of the project
>>./tmp.out
Best leaf by tree traversal has score: 8
Best leaf associated state has -1977735524 values in its attribute vector though! (Should be 4)
What I'd expect:
>>g++ -std=c++17 -o tmp.out tests/test.cpp // <- require c++17 for other parts of the project
>>./tmp.out
Best leaf by tree traversal has score: 8
Best leaf associated state has 4 values in its attribute vector though! (Should be 4)
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
class Board{
vector<int> attribute;
string name;
public:
Board(){
attribute = {1,2,3,4};
name = "nonempty name";
}
Board getcopy(){
return *this;
}
int AttrLen(){
return attribute.size();
}
};
class Node{
Board* board;
Node* parent;
std::vector<Node*> children;
int depth=0;
int score=0;
bool terminal=false;
public:
Node(Node* _parent, Board* _board,int _depth){
parent = _parent;
board = _board;
depth = _depth;
// randomize score
score = rand() % 10;
if(depth<2){
for(int _=0;_<2;_++){
Board new_state = board -> getcopy();
children.push_back(new Node(this,&new_state,depth+1));
}
} else {
children = {};
terminal=true;
}
}
int getScore(){
return score;
}
bool isTerminal(){
return terminal;
}
Node* getBestChild(){
if(!terminal){
if(children[0] ->getScore() > children[1] -> getScore()){
return children[0];
} else {
return children[1];
}
} else {
return nullptr;
}
}
Board* getStateptr(){
return board;
}
};
int main(){
// make a board
Board my_board = Board();
// make a root node
Node root = Node(nullptr, &my_board, 0);
Node* best_child = root.getBestChild();
while(!best_child -> isTerminal()){
best_child = best_child -> getBestChild();
}
cout << "Best leaf by tree traversal has score: " << best_child -> getScore() << endl;
cout << "Best leaf associated state has " << best_child -> getStateptr() ->AttrLen() << " values in its attribute vector though! (Should be 4)" << endl;
}
Not sure if this is the only problem, but here
for(int _=0;_<2;_++){
Board new_state = board -> getcopy();
children.push_back(new Node(this,&new_state,depth+1));
}
Your create a copy of Board which only lives inside the for loop. It gets destroyed automatically at }. Hence the pointers you store in the node are dangling. The point to objects that are long gone.
Note that your getcopy is a bit weird. You should use a copy constructor instead. In general, when your type mangages resources via raw pointers (not sure if it actually is the case) then you need to respect the rule of 3/5. In any case you can copy a board simply by writing Board new_state = *board; (assuming the compiler generated copy constructor does the right thing).

C++ Pointer target returning wrong value

I am a fairly experience C# programmer and trying to help out a friend with a C++ application that creates a Stack object. It has been well over 13 years since I've even seen C++ and I am having a damn fine time trying to recall the proper way to do this. It took me a bit to get up to speed on the Header/CPP distinction again, so there may be issues in there even. Here is my problem:
//Stack.h
#ifndef __STACK_INCLUDED__
#define __STACK_INCLUDED__
#include "Node.h"
class Stack
{
private:
/// Going to be the pointer to our top node
Node* m_topNode;
/// Running count of elements
int m_count;
public:
///Constructor
Stack();
///Allows us to retrieve the top value from the stack
/// and remove it from the stack
int Pop();
.
.
.
};
#endif
Below is the CPP that matches the header. I am doing in here JUST for debugging at the moment. I am also fully qualifying everything because I was not sure if that is causing issues with the pointers and loss of references.
//Stack.cpp
#include "stdafx.h"
#include "Stack.h"
#include <iostream>
Stack::Stack(){
m_count = 0;
m_topNode = NULL;
}
void Stack::Push(int Value){
std::cout << "\nPushing Value: ";
std::cout << Value;
std::cout << "\n";
if ( Stack::m_topNode )
{
std::cout << "TopNode Value: ";
std::cout << Stack::m_topNode->data;
std::cout << "\n";
}
std::cout << "\n";
Node newNode(Value, NULL, Stack::m_topNode);
Stack::m_topNode = &newNode;
Stack::m_count++;
}
The node class is a pretty simple entity. Just needs to store a value and the pointers on either side. I know I don't need to track in both directions for a Stack but I wanted to make this something that was easily changed to a Queue or similar construct.
//Node.h
#ifndef __NODE_INCLUDED__
#define __NODE_INCLUDED__
class Node
{
private:
public:
///Constructor allows us to specify all values.
/// In a stack I expect NextNode to be NULL
Node(int Value,Node* NextNode, Node* PreviousNode);
///Pointer to the next node
Node* Next;
///Pointer to the previous node
Node* Prev;
///Value to be stored
int data;
};
#endif
Very simple implementation:
//Node.cpp
#include "stdafx.h"
#include "Node.h"
Node::Node(int Value, Node* NextNode, Node* PreviousNode){
data = Value;
Next = NextNode;
Prev = PreviousNode;
}
My main is just about sending 2 values to the stack right now via Push and seeing what the values are printing:
#include "stdafx.h"
#include "Node.h"
#include "Stack.h"
using namespace std;
int main(){
Stack s = Stack();
for ( int i = 0; i < 2; i++ ){
s.Push(i * 10);
}
int blah;
cin >> blah; //Stall screen
return 0;
}
Here is the Output:
Pushing Value: 0
<blank line>
Pushing Value: 10
TopNode Value: -858993460
When I hit Node newNode(Value, NULL, Stack::m_topNode) in the debugger I can see it tracking the proper value in the current node, but m_topNode references a really odd value. I'm hoping it's very obvious that I'm doing something dumb as I don't remember this being this tricky when I did it years ago. Appreciate any help/insight to my incorrect manners.
Node newNode(Value, NULL, Stack::m_topNode);
Stack::m_topNode = &newNode;
Stack::m_count++;
This is your problem. You allocate the new node on the current stack, and then put the pointer into the linked list of nodes. This pointer will be invalid as soon as your stack frame returns, and all hell breaks lose. ;)
You need to allocate the node with new.
As stated by Norwæ, you need to allocate your newNode with "new" because if you dont, your newNode is static and will be out of scope at the end of the Push function.
You also need to call your private members without the "Stack::" as this is used in C++ only to access static class members and functions. replace "Stack::m_topNode" for "m_topNode" only, and Stack::m_count for m_count.
Here is a working Push function :
void Stack::Push(int Value){
std::cout << "\nPushing Value: ";
std::cout << Value;
std::cout << "\n";
if ( m_topNode )
{
std::cout << "TopNode Value: ";
std::cout << m_topNode->data;
std::cout << "\n";
}
std::cout << "\n";
Node * newNode = new Node(Value, NULL, m_topNode);
m_topNode = newNode;
m_count++;
}
This line:
std::cout << Stack::m_topNode->data;
happens before
Node newNode(Value, NULL, Stack::m_topNode);
Stack::m_topNode = &newNode;
Stack::m_count++;
So you're trying to print an uninitialized value. Reverse these and see what happens.

Segfault in recursive function

I'm getting a segfault when I run this code and I'm not sure why. Commenting out a particular line (marked below) removes the segfault, which led me to believe that the recursive use of the iterator "i" may have been causing trouble, but even after changing it to a pointer I get a segfault.
void executeCommands(string inputstream, linklist<linklist<transform> > trsMetastack)
{
int * i=new int;
(*i) = 0;
while((*i)<inputstream.length())
{
string command = getCommand((*i),inputstream);
string cmd = getArguments(command,0);
//cout << getArguments(command,0) << " " << endl;
if (cmd=="translate")
{
transform trs;
trs.type=1;
trs.arguments[0]=getValue(getArguments(command,2));
trs.arguments[1]=getValue(getArguments(command,3));
((trsMetastack.top)->value).push(trs);
executeCommands(getArguments(command,1),trsMetastack);
}
if (cmd=="group")
{
//make a NEW TRANSFORMS STACK, set CURRENT stack to that one
linklist<transform> transformStack;
trsMetastack.push(transformStack);
//cout << "|" << getAllArguments(command) << "|" << endl;
executeCommands(getAllArguments(command),trsMetastack); // COMMENTING THIS LINE OUT removes the segfault
}
if (cmd=="line")
{ //POP transforms off of the whole stack/metastack conglomeration and apply them.
while ((trsMetastack.isEmpty())==0)
{
while ((((trsMetastack.top)->value).isEmpty())==0) //this pops a single _stack_ in the metastack
{ transform tBA = ((trsMetastack.top)->value).pop();
cout << tBA.type << tBA.arguments[0] << tBA.arguments[1];
}
trsMetastack.pop();
}
}
"Metastack" is a linked list of linked lists that I have to send to the function during recursion, declared as such:
linklist<transform> transformStack;
linklist<linklist<transform> > trsMetastack;
trsMetastack.push(transformStack);
executeCommands(stdinstring,trsMetastack);
The "Getallarguments" function is just meant to extract a majority of a string given it, like so:
string getAllArguments(string expr) // Gets the whole string of arguments
{
expr = expr.replace(0,1," ");
int space = expr.find_first_of(" ",1);
return expr.substr(space+1,expr.length()-space-1);
}
And here is the linked list class definition.
template <class dataclass>
struct linkm {
dataclass value; //transform object, point object, string... you name it
linkm *next;
};
template <class dataclass>
class linklist
{
public:
linklist()
{top = NULL;}
~linklist()
{}
void push(dataclass num)
{
cout << "pushed";
linkm<dataclass> *temp = new linkm<dataclass>;
temp->value = num;
temp->next = top;
top = temp;
}
dataclass pop()
{
cout << "pop"<< endl;
//if (top == NULL) {return dataclass obj;}
linkm<dataclass> * temp;
temp = top;
dataclass value;
value = temp->value;
top = temp->next;
delete temp;
return value;
}
bool isEmpty()
{
if (top == NULL)
return 1;
return 0;
}
// private:
linkm<dataclass> *top;
};
Thanks for taking the time to read this. I know the problem is vague but I just spent the last hour trying to debug this with gdb, I honestly dunno what it could be.
It could be anything, but my wild guess is, ironically: stack overflow.
You might want to try passing your data structures around as references, e.g.:
void executeCommands(string &inputstream, linklist<linklist<transform> > &trsMetastack)
But as Vlad has pointed out, you might want to get familiar with gdb.

Need help with copy constructor for very basic implementation of singly linked lists

Last week, we created a program that manages sets of strings, using classes and vectors. I was able to complete this 100%. This week, we have to replace the vector we used to store strings in our class with simple singly linked lists.
The function basically allows users to declare sets of strings that are empty, and sets with only one element. In the main file, there is a vector whose elements are a struct that contain setName and strSet (class).
HERE IS MY PROBLEM: It deals with the copy constructor of the class. When I remove/comment out the copy constructor, I can declare as many empty or single sets as I want, and output their values without a problem. But I know I will obviously need the copy constructor for when I implement the rest of the program. When I leave the copy constructor in, I can declare one set, either single or empty, and output its value. But if I declare a 2nd set, and i try to output either of the first two sets, i get a Segmentation Fault. Moreover, if i try to declare more then 2 sets, I get a Segmentation Fault. Any help would be appreciated!!
Here is my code for a very basic implementation of everything:
Here is the setcalc.cpp: (main file)
#include <iostream>
#include <cctype>
#include <cstring>
#include <string>
#include "strset2.h"
using namespace std;
// Declares of structure to hold all the sets defined
struct setsOfStr {
string nameOfSet;
strSet stringSet;
};
// Checks if the set name inputted is unique
bool isSetNameUnique( vector<setsOfStr> strSetArr, string setName) {
for(unsigned int i = 0; i < strSetArr.size(); i++) {
if( strSetArr[i].nameOfSet == setName ) {
return false;
}
}
return true;
}
int main() {
char commandChoice;
// Declares a vector with our declared structure as the type
vector<setsOfStr> strSetVec;
string setName;
string singleEle;
// Sets a loop that will constantly ask for a command until 'q' is typed
while (1) {
cin >> commandChoice;
// declaring a set to be empty
if(commandChoice == 'd') {
cin >> setName;
// Check that the set name inputted is unique
if (isSetNameUnique(strSetVec, setName) == true) {
strSet emptyStrSet;
setsOfStr set1;
set1.nameOfSet = setName;
set1.stringSet = emptyStrSet;
strSetVec.push_back(set1);
}
else {
cerr << "ERROR: Re-declaration of set '" << setName << "'\n";
}
}
// declaring a set to be a singleton
else if(commandChoice == 's') {
cin >> setName;
cin >> singleEle;
// Check that the set name inputted is unique
if (isSetNameUnique(strSetVec, setName) == true) {
strSet singleStrSet(singleEle);
setsOfStr set2;
set2.nameOfSet = setName;
set2.stringSet = singleStrSet;
strSetVec.push_back(set2);
}
else {
cerr << "ERROR: Re-declaration of set '" << setName << "'\n";
}
}
// using the output function
else if(commandChoice == 'o') {
cin >> setName;
if(isSetNameUnique(strSetVec, setName) == false) {
// loop through until the set name is matched and call output on its strSet
for(unsigned int k = 0; k < strSetVec.size(); k++) {
if( strSetVec[k].nameOfSet == setName ) {
(strSetVec[k].stringSet).output();
}
}
}
else {
cerr << "ERROR: No such set '" << setName << "'\n";
}
}
// quitting
else if(commandChoice == 'q') {
break;
}
else {
cerr << "ERROR: Ignoring bad command: '" << commandChoice << "'\n";
}
}
return 0;
}
Here is the strSet2.h:
#ifndef _STRSET_
#define _STRSET_
#include <iostream>
#include <vector>
#include <string>
struct node {
std::string s1;
node * next;
};
class strSet {
private:
node * first;
public:
strSet (); // Create empty set
strSet (std::string s); // Create singleton set
strSet (const strSet &copy); // Copy constructor
// will implement destructor and overloaded assignment operator later
void output() const;
}; // End of strSet class
#endif // _STRSET_
And here is the strSet2.cpp (implementation of class)
#include <iostream>
#include <vector>
#include <string>
#include "strset2.h"
using namespace std;
strSet::strSet() {
first = NULL;
}
strSet::strSet(string s) {
node *temp;
temp = new node;
temp->s1 = s;
temp->next = NULL;
first = temp;
}
strSet::strSet(const strSet& copy) {
cout << "copy-cst\n";
node *n = copy.first;
node *prev = NULL;
while (n) {
node *newNode = new node;
newNode->s1 = n->s1;
newNode->next = NULL;
if (prev) {
prev->next = newNode;
}
else {
first = newNode;
}
prev = newNode;
n = n->next;
}
}
void strSet::output() const {
if(first == NULL) {
cout << "Empty set\n";
}
else {
node *temp;
temp = first;
while(1) {
cout << temp->s1 << endl;
if(temp->next == NULL) break;
temp = temp->next;
}
}
}
The C++ standard states that types used in a standard container (such as std::vector) must be copy constructable AND assignable.
Since you have not implemented a custom assignment operator on the class strSet, the compiler will generate one for you that does a simple memberwise copy. In your case, this means the 'first' pointer will be copied directly. Obviously this means two objects now 'own' the nodes in the set, and you will get a crash when it is freed twice.
Some tips:
Implement a custom assignment operator that does the same thing as your copy constructor
Read up on passing objects by reference, and by const reference where possible. You are doing a lot of unnecessary copying of your containers and strings when you pass by value.
e.g.
bool isSetNameUnique(const vector& strSetArr, const string& setName)
Good luck :)
this looks a bit peculiar:
strSet::strSet(string s) {
node *temp;
temp = new node;
temp->s1 = s;
temp->next = NULL;
first = temp;
}
what if 'first' is pointing to something already? You are then effectively killing the previous list and causing a mem leak.
Your strSet copy constructor does not assign the member first when its argument is empty. This causes Undefined Behavior.
Also, the strSet assignment operator (operator=) that was shown before the edit was definitely wrong; and it really is not a good idea to define a copy constructor but allow the destructor and assignment operator to be implicitly defined by the compiler. See the Rule of Three.
One common way to implement the Big Three when they need to do considerable management (like in this case) looks something like:
class strSet {
private:
void cleanup();
void create_from(const node* n);
// ...
};
strSet::~strSet() { cleanup(); }
strSet::strSet(const strSet& copy) : first(NULL) { create_from(copy.first); }
strSet& strSet::operator=(const strSet& rtSide) {
if (this != &rtSide) {
cleanup(); // trash old contents of *this
create_from(rtSide.first); // clone contents of rtSide
}
return *this;
}