What is the uses of using a pointer in this specific scenario? - c++

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.

Related

How to properly read from .txt file and assign to structs with pointer, C++

I am trying to read a file and deserialize it. I take two string in at a time and assign it to some variable foo and bar. First foo is assigned to NODE2 and ofc the bit vector, then bar is assigned to NODE2, but when this happens foo is also assigned to NODE2. I suspect that it has something to do with the pointers but I want to have the struct NodeReading to have a pointer to a string to relief the space of the tree that I will eventually build. I plan to have several hundred thousands of NodeReadings in a Binary tree. I just want to have the string stored as a pointer, because the strings are going to be large as well. It's only the leafs which will store an actual string (Internal nodes are used to navigate based on their bitset).
#include <iostream>
#include <fstream>
using namespace std;
struct Read {
string dna;
bitset<5> bf;
};
struct NodeReading {
bitset<5> bloom_filter;
string* dna_string;
};
static const string file = "tree.txt";
ifstream ist {file};
//could be a pair return instead of Read, but I like it this way.
Read read_line() {
string a;
bitset<5> b;
ist >> a >> b;
return Read {a, b};
}
NodeReading write_to_tree() {
Read s = read_line();
NodeReading hey {s.bf, &s.dna};
return hey;
}
int main {
NodeReading foo = write_to_tree(); //gets assigned NODE1 at first
NodeReading bar = write_to_tree(); //gets assigned NODE2, and then foo also gets assigned NODE2
return 0;
}
tree.txt:
NODE1 11110 NODE2 11110
Whatever happening is actually an undefined behavior. If you are doing some other processing between between these two line - NodeReading foo = write_to_tree(); & NodeReading bar = write_to_tree(); and then try to access foo, then chances that your application crashes because of segmentation fault.
Inside write_to_tree() your variable Read s is not allocated on heap, so as soon as you return from that function, variable Read s goes out of scope and you lost all the data in that. You need to allocate it on heap.
In your code struct NodeReading looks redundant. You can directly use struct Read, struct NodeReading is just a copy of struct Read's bit field and a pointer to its string.

passing struct by reference in c++ doesnt update the value

i am passing a struct by reference to one function of a class treestr and storing it there in a vector.
Then passing the same struct by reference to another function and performing some computation on data member of struct. This data member gets updated in the original struct but not in the ones stored in the vector.
(Sorry for any mistakes, new to c++, new to stack overflow). Please help.
//Structure description
Struct point{
int x;
int y;
int cal{0};
};
Struct node{
point p;
int data; //value to be updated by func
};
int main(){
treestr * tree= new treestr(); //create object
int i=0,n=100;
vector<node> nob;
while(i<=n){
p={1,5}; //some values input by user
node n={p,i};
nob.push_back(n)//storing the struct node objects seperately in a
//vector
treestr->insert(n); //inserting into tree class
i++;
}
//calling func to do some computation on the struct objects inserted
for(i=0;i<n;i++){
int x=tree->func(nob[i]);
cout<<x.cal; //getting updated values from the function
}
for(i=0;i<N;i++){
tree->func2(nob[i]);
}
return 0;
}
//class description
class treestr{
vector<node> buck;
insert(node& n){
buck.push_back(n);
//store nodes
}
func(node& n){
//calculations
return n.cal; Value got updated in main.
}
func2(node &n){
int val1=n.cal; //this assigns updated value
int val2=buck[i].p.cal; //this assigns 0(default value)
if(val1==val2){ //never matches, val2 is 0 for all objects, val1 is
//not after getting updated
//do something
}
}
};
The cal gets updated in the main function but not in the class where I have stored. Please ignore grammatical and syntactical mistakes, the code returns correct output however this is something that I need to improve my code.
Any possible reasons??
Try changing
node n={1,5,0}
to
node * n;
node -> x = 1;
node -> y = 5;
node -> cal = 0;
From what I know of pointers you need to assign each value individually.
Also
tree->insert(n)
needs to be
tree.insert(n)
Another thing
int node.cal=tree->func(n);
Not sure what this is supposed to do, but I know it won't work. 'int' needs to be before a variable name. When accessing cal from node your call needs to be an -> and when accessing func from tree it needs to be a .

Cannot copy struct's items into another struct

I have struct Node and struct UniqueInstructor. Both are singly-linked lists. I have already filled struct Node with some values. Now what I need to do is fill the second UniqueInstructor struct with Node's struct specific value (std::string instructor).
This is how my structs look like:
// main struct that I already filled with data
struct Node {
Node* pNext;
std::string data1;
std::string data2;
std::string day;
std::string group;
std::string instructor; // these are the items I want to copy
// into the UniqueInstructor struct
std::string course;
};
// my 'target' struct, also linked list
struct UniqueInstructor {
UniqueInstructor* pNext;
std::string instructor;
};
For now, all I need to do is copy all the std::string instructor values from Node into UniqueInstructor.
I have tried bunch of things, such as:
void DuplicateInstructor(Node *&pHead)
{
pHead = new UniqueInstructor { pHead, pHead->instructor };
}
but I am getting errors. In this case:
cannot convert 'Node*' to 'UniqueInstructor*' in initialization
My problem probably lies somewhere in passing struct into that function. Please be forgiving, I am fresh-new to structs and pointers. Thank you for help.
You just need to copy the Node::instructor field into the UniqueInstructor::instructor field. Both fields are std::string so that is no problem.
void like_this(Node& n, UniqueInstructor& i)
{
i.instructor = n.instructor;
}
Now it's not very clear what you actually trying to achieve and what your program structure is so I can't tell you where or how you get the Instructor object. In the example above both objects exist. Also you can't link a Node with an UniqueInstructor. Simply Node::pNext and UniqueInstructor::pNext are of completely different types, so I don't know what you are trying to do here.
Moreover explicit new / delete calls are a very bad practice. They have absolutely no place in C++ (outside of library implementations). Too much headache and more importantly too much room for bugs (memory leaks on exceptions). Please read about RAII and smart pointers in C++.

simple cpp map store and access not working as expected

I have the following code which uses map to insert Nodes into mp according to a key. The class has two functions set and get to insert and access the map respectively.
struct Node {
int value;
int key;
Node(int k, int val):key(k),value(val) {};
};
class Cache {
private:
map<int, Node*> mp;
Node* tail;
Node* head;
public:
void set(int, int);
void get(int);
};
void Cache::set(int key, int value) {
Node newN = Node(key, value);
mp.insert(std::pair<int, Node*>(key, &newN));
}
void Cache::get(int key) {
auto s = this->mp.find(key);
if (s != this->mp.end()) {
Node *nHit = s->second;
std::cout << "Map key = " << s->first;
std::cout << " : Node Key = " << nHit->key;
std::cout << ", value = " << nHit->value << "\n";
}
}
A driver main function implementation is below, which takes input of 2 lines and outputs key and value.
int main() {
int i;
Cache l;
for(i = 0; i < 2; i++) {
string command;
cin >> command;
if(command == "get") {
int key;
cin >> key;
l.get(key);
}
else if(command == "set") {
int key, value;
cin >> key >> value;
l.set(key, value);
}
}
return 0;
}
Input -
set 2 3
get 2
Output -
Map key = 2 : Node Key = 32764, value = -491659096
Note - The output key and value keeps changing and are not fixed with each run.
Why and how is the key and value getting changed for the map here?
You are inserting a pointer to a function-scoped value. When the function set() exits the value newN is destroyed, and the pointer held in the map is invalid.
Either you really want a map with an instance of Node as the value; or you need to use new in set() to allocate your object, but then you also need to remember to delete it. You could use "smart" pointers such as shared_ptr or unique_ptr to help manage this lifetime - though unique_ptr won't get you any advantages over using an instance.
In C++, a piece of data is typically tied to a single location. If that location is a variable in some { block scope; }, then the variable is deleted at the closing }. For instance, the closing bracket of Cache::set deletes newN, and any references to it (including pointers in mp) no longer point anywhere.
C++ has a second option: the lifetime of some data can be controlled by a class. For instance, the int and Node* values you put in mp get deleted along with mp. So rather than storing Node* in mp, you can store Node directly, instead of its address!
The declaration of mp should be
map<int, Node*> mp;
You can insert with
void Cache::set(int key, int value) {
mp.emplace(key, Node(key, value));
}
And then in main you can have
Node &nHit = s->second;
And then you can get members of nHit with . instead of ->.
Your other alternative is to use smart pointers, as Jesper Juhl mentioned. Store std::unique_ptr<Node> in mp if you're using pointers only for polymorphism with virtual methods, and std::shared_ptr<Node> is useful if you want some of your Node objects to be used in several places and mp.
Taking the address of an object with & (e.g. to create Node*) is very useful if you want to just reference an object of known lifetime, and you want to store that reference inside of some other object of a shorter lifetime.
DO NOT use new Node(key, value) except in a smart pointer constructor, unless you're prepared to individually delete every Node* yourself, and never make mistakes.
You have to allocate Node using new. E.g.,
Node *newN = new Node(key, value);
mp.insert(std::pair<int, Node*>(key, newN));
As it is your Node is on the stack and goes out of scope when the function returns.

Struct in Struct with vectors Segmentation Fault

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