I have two structs ITEM and TABLE, one of which contains the other one, i.e. TABLE contains many ITEMS. I use this code to create the structs and the table and items with it.
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
struct ITEM {
std::string itemTitle;
};
struct TABLE {
std::string tableName;
int num;
ITEM* items;
};
TABLE setTABLE(std::string, int num) {
struct ITEM* item = (struct ITEM*) malloc(sizeof(struct ITEM) * num);
TABLE table = {tableName, num, item};
return table;
}
int main() {
std::vector<TABLE> tables;
tables.push_back(setTABLE("TEST", 3));
tables[0].items[0].itemTitle = "TestItem";
std::cout << tables[0].items[0].itemTitle << "\n";
return 0;
}
I want to set the itemTitle of the ITEM at position 0, but when I cout the result i get
Segmentation fault: 11
I guess the malloc is not sufficient to this? Or is my code construction misconstrued in the first place? What I wanted to achieve is build a custom table structure.
malloc() allocates memory, whereas new allocates memory and initializes (invoking a constructor of an object for example). As malloc() is being used items is a pointer to allocated but uninitialized memory which is accessed at:
tables[0].items[0].itemTitle = "TestItem";
causing the segmentation fault. But, don't use new just use a std::vector<ITEM> instead. An initial size is not required but can be supplied if required and the vector constructed with n default elements:
struct Table
{
Table(std::string const& aName, const size_t a_num) :
tableName(aName), items(a_num) {}
std::string tableName;
std::vector<Item> items;
};
Note num no longer required as items.size() can be used and don't use all uppercase as these are generally used for macros.
you are returning variable table which is created on the stack -- you will need to malloc memory for table first
Related
I have a vector of instances of a class called Node. I want to be able to condition on whether or not specific indices of the vector are populated or not.
See the example code below:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class Node {
int testVal;
public:
//Default Constructor
Node() {};
Node(int a){testVal = a;}
int getTestVal(){return testVal;}
};
int main(){
vector<Node> testVector;
testVector.resize(2);
Node testNode = Node(5);
testVector[1] = testNode;
for (int i = 0;i < 2;i++){
if (testVector[i] == NULL){
cout << "Missing Data" << endl;
}
else{
cout << testVector[i].getTestVal << endl;
}
}
}
The code crashes at the if statement. What is a good way to condition on if a specific index is empty?
What you are asking is not possible.
The vector stores values not pointers, and so you will never get null.
If you want to check for "empty" spots, then declare a vector that stores the address of the nodes:
std::vector<std::shared_ptr<Node>> testVector;
And to store an item in the second index of the vector you do:
testVector[1] = std::make_shared<Node>(5);
Now the rest of your code should work as expected (just need to fix that call to getTestVal() function).
I think you misunderstand C++ semantics.
std::vector< Node> testVector; // creates empty vector of Node objects, no Node allocations made here
testVector.resize( 2 ); // calls default constructor and instantiates 2 new Node objects here
// could be done as std::vector< Node > testVector( 2 );
That vector has already allocated memory for those 2 Nodes it exists as the default constructor defines the class. It sounds like you want something more like this:
...
std::vector< Node * > testVector( 2, null_ptr );
testVector[ 1 ] = new Node( 5 );
for( const auto & ptr : testVector )
if( ptr )
std::cout << ptr->getTestVal() << std::endl;
...
delete testVector[ 1 ];
As someone else mentioned, smart pointer objects can also be used to manage memory for you and behave similarly.
I have a table object with the following header file:
#ifndef TABLE_H
#define TABLE_H
#include "Order.h"
#include "Waiter.h"
// 0 1 2 3
enum TableStatus { IDLE, SEATED, ORDERED, SERVED };
class Waiter; // to take care of circular reference.
class Table
{
private:
int tableId; // table number
const int maxSeats; // table seat capacity
TableStatus status; // current status, you can use assign like
// status = IDLE;
int numPeople; // number of people in current party
Order *order; // current party's order
Waiter *waiter; // pointer to waiter for this table
public:
Table(int tblid =0, int mseats = 0); // initialization, IDLE
void assignWaiter(Waiter *person); // initially no waiter
void partySeated(int npeople); // process IDLE --> SEATED
void partyOrdered(Order *order); // process SEATED --> ORDERED
void partyServed(void); // process ORDERED --> SERVED
void partyCheckout(void); // process SERVED --> IDLE
int getMaxSeats(void);
int getStatus(void);
};
#endif
in my main function, I need to declare an array of tables. But when I write, say, Table *table = new Table[10], every element of the array calls the default arguments in the constructor, and every table ends up with a constant maximum seat value of 0. I need to be able to individually call each of their constructors to have different values for the maxSeats.
The only solution I've been able to come up with so far is to declare an array of pointers to table objects, and then instantiate each one separately. This partially works, but the Waiter class mentioned in the code above accepts an array of Tables as an argument, and won't work if it's passed an array of Table pointers.
What process can i perform to end up with an array of Table objects with differing values for their maxSeats constant variable?
One more point of clarification: The array has to be dynamically created, so I can't just explicitly make 10 or however many calls to the constructor. I don't know in advance how large the array must be.
One option is to use placement new:
Table* tables = static_cast<Table*>(new char[sizeof(Table) * count]);
for(int i = 0; i < count; i++) new(&tables[i]) Table(tblid[i], mseats[i]);
You can use a placement new in this particular situation, but do not forget to manually destruct your objects, and deallocate the raw memory with operator delete[] : (If you don't, your program will have undefined behavior)
Here is a minimal example of a placement new with array objects:
#include <new>
class MyClass
{
public:
MyClass(int i) : p(i) {}
private:
int p;
};
int main(int argc, char** argv) {
// Allocate a raw chuck of memory
void* buff10 = operator new[](sizeof(MyClass) * 10);
MyClass * arr = static_cast<MyClass*>(buff10);
// Construct objects with placment new
for(std::size_t i = 0 ; i < 10 ; ++i)
new (arr + i) MyClass(i);
// Use it ...
// Then delete :
for(std::size_t i = 9 ; i >= 0 ; --i)
arr[i].~MyClass();
operator delete[] (arr);
return 0;
}
It's not possible to do this with new. But you should not be using new anyway. Use vector instead. Before C++11 it can't really cope with a const member, but in C++11 you have some options:
std::vector<Table> table = {
{ 1, 1 }, {2, 2}, {3, 3}, /* etc. */ };
Or you can add one by one:
std::vector<Table> table;
table.emplace_back( Table(1, 1) );
table.emplace_back( Table(2, 2) );
Since your class contains a const that makes it non-copyable. However it is still MoveConstructible.
Note: It probably makes things a lot easier here if you don't have a const class member, just keep it private and don't change it.
Also, depending on what you do with order and waiter, the default move constructor might not do the right thing. If these point to resources which are "owned" by the table then you will have to either manage these resources properly, or write your own a move constructor.
I need to save objects as pointers in dynamic array but i have problem.
This is my code, there are three classes and i need to have array (arrayoftwo) of poiters to class Two that would work further with class Three and so on. I have two problems. One is that i cant figure out how to dynamically allocate space for my arrayoftwo (which i need to dynamically resize by number of stored pointers) and second problem is how to exactly store pointers to objects without destroying object itself.
Here is my code:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
using namespace std;
class One {
public:
bool addTwo(int a);
private:
void getspace(void);
class Two {
public:
int a;
private:
class Three {
/*...*/
};
Three arrayofThree[];
};
int freeindex;
int allocated;
Two *arrayoftwo[];
};
void One::getspace(void){
// how to allocate space for array of pointers ?
arrayoftwo=new *Two[100];
allocated=100;
}
bool One::addTwo(int a){
Two temp;
temp.a=a;
getspace();
arrayoftwo[freeindex]=&temp;
freeindex++;
return true;
//after leaving this method, will the object temp still exist or pointer stored in array would be pointing on nothing ?
}
int main() {
bool status;
One x;
status = x . addTwo(100);
return 0;
}
Thank you for any help.
EDIT: I cant use vector or any other advanced containers
temp will not exist after leaving addTwo; the pointer you store to it is invalid at that point. Instead of storing the object as a local variable, allocate it on the heap with new:
Two* temp = new Two();
To allocate an array of pointers:
Two** arrayoftwo; // declare it like this
// ...
arrayoftwo = new Two*[100];
And getspace should either be passed a (from addTwo) or a should be stored as the member variable allocated and getspace should access it from there. Otherwise it's assuming 100.
In this scenario, I have a struct Data declared.
struct Data {
string first;
string middle;
string last;
int age;
};
According to my notes, we then create a
vector<Data*> list;
To add items to this list, we have to create a new data pointer and set attributes manually.
Data* variable;
variable=new Data;
list.pushback<variable>
I do not see the merits of using this approach. Why can't we just use this?
vector<Data> list;
To add items to this list, I create a new Data variable, then use
list.pushback<variable>;
Am I right to say both approaches works?
First of all it has to be
list.push_back(variable)
instead of
list.pushback<variable>
The difference is that in case 1 you create a pointer to the variable, which means you only store the adress of variable in the list. This code
#include <string>
#include <vector>
#include <iostream>
using namespace std;
struct Data {
string first;
string middle;
string last;
int age;
};
int main()
{
vector<Data*> list;
Data* variable;
variable = new Data;
list.push_back(variable);
cout << list[0];
cin.get();
return 0;
}
would only return you the address of the place in memory where variable was stored.
So to return some value of variable you could use something like
vector<Data*> list;
Data* variable;
variable = new Data;
variable->setage(5);
list.push_back(variable);
cout << (*list[0]).getage();
cin.get();
return 0;
}
Where *list[0] dereferences the pointers, that means you get the value and not the adress of it.
If you work without pointers instead
vector<Data> list;
Data variable;
list.push_back(variable);
instead, you would store a copy of variable in the list.
So in this case you could directly address variable by something like
list[0].getage()
if you create a getage() function in the struct Data.
If you don't know how to do so, an easy( maybe not the best) way is to add
public:
int getage(){
return age;
}
void setage(int x){
age = x;
}
};
in your struct Data.
It is faster.
For your case, if you were to do
Data variable;
// change properties here
list.push_back(variable);
you would first create a struct Data on the first line, and then you would copy the entire struct when it was pushed back into the list. Since the struct is larger than a pointer to it, doing so is simply not as computationally efficient as just pushing the struct pointer.
I have a class like this:
classA
{
public:
classA()
{
//Here I am doing something but nothing related to vector
}
void updateVec(int idx, int value)
{
//Here, I want to update vector vector based on args passed
myVec.insert(myVec.begin() + idx, value);
}
std::vector<int> myVec;
}
Now, I am getting segmentation fault on insert statement. Do I need to initialize vector somewhere?
Segmentation fault means you're trying to access/write into memory that has not (yet) been allocated. In your case, depending on value of idx, myVec.begin() + idx can refer to memory that is out of vector's allocated zone. Before inserting, you need to make sure your vector can hold at least idx elements. updateVec should check the current size of the vector, and if it is not big enough, it should call vector::reserve to allocate enough room so new element can be inserted.
From your code it seems that you did not initialize it properly.
initialization for use as local var
Create a vector of ints, size 3, initialized to 0
std::vector<int> myvector (3,0);
Short example of how to initialize(and then resize) a vector in a class's constructor
#include <iostream>
#include <vector>
class A {
public:
A(int size);
~A();
void updateVec(int idx, int value);
void print();
private:
std::vector<int> myVec;
};
A::A(int size) {
myVec.resize(size);
}
A::~A() {
}
void A::updateVec(int idx, int value) {
myVec.insert(myVec.begin() + idx, value);
}
void A::print() {
std::vector<int>::iterator it;
for (it=myVec.begin(); it!=myVec.end(); it++) {
std::cout << " " << *it;
}
}
int main() {
A* a = new A(10);
a->updateVec(2,10);
a->print();
}
Here is documentation/example on how to use a vector in C++
http://www.cplusplus.com/reference/stl/vector/insert/
Yes, you do. Vectors start off empty. Any attempt to access an item past the end of the vector will result in an error.
To suggest a solution we'll need to know if the vector needs to change size dynamically - or if it is a fixed size, at what point in time will you know what size it needs to be.
Also, if you update the 17th elemnt of the vector, but at the time it only contains 10 items, do you want items 11 to 16 to be created as well?