how to change address of variable? - c++

i have
Tree<std:string> tree;
now
new Tree<std:string>;
leads to a pointer,
how can i change address of tree to that of pointer generated by new?

Making C++ code look like Java is a bad idea, the two languages are very different.
That said, in C++ operator new returns a pointer to the allocated object.
Tree<std::string> * tree = new Tree<std::string>;
tree->do_something();
You can also bind a reference to your object.
Tree<std::string> & tree2 = *tree;
tree.do_something();
I urge you not to do that. Writing -> instead of . is not that difficult.

I think you're a little confused here.
In C++ when you declare an object, the constructor is called automatically, you don't need to new it. After doing:
Tree<std:string> tree;
You can access tree already, and its constructor has been called.
It is already a constructed object. If you want to have a pointer, and construct an object in the heap, and no the stack, you need to do,
Tree<std:string> *tree;
tree = new Tree<std:string>;
And then use *tree to access tree.
You can see how it works if you add a printf statement to the constructor.

You can't. Creating an object using Tree<std:string> tree; creates tree at some specific place in memory and you can't change that.
Perhaps what you want is to make tree be a pointer Tree<std:string> *tree = 0;. When you do that, tree is no longer an object but a pointer. You can then make it point to an object by assigning the return from new tree = new Tree<std::string>;

I'd also recommend to read Alok's comment and think a bit about it.
Here you have examples of alternative approaches of transition from automatic storage to dynamic storage. It uses std::vector as equivalent to your Tree class, but it can be any type you like.
#include <algorithm>
#include <iostream>
#include <iterator>
#include <string>
#include <vector>
using namespace std;
int main()
{
vector<string> v(3);
v[0] = "abc";
v[1] = "def";
v[2] = "ghi";
// option #1 - make a copy
{
vector<string>* pv = new vector<string>(v);
std::copy(pv->begin(), pv->end(), std::ostream_iterator<string>(cout, ", "));
delete pv;
}
cout << endl;
// option #2 - move content from original vector to new'ed one
{
vector<string>* pv = new vector<string>();
pv->swap(v);
std::copy(pv->begin(), pv->end(), std::ostream_iterator<string>(cout, ", "));
delete pv;
}
}

Related

Deleting dynamic array in C++ causes an error

I have a class called Myclass. In the main function, I have created an array object for this class. Whenever I try to delete this dynamically allocated array, the visual studio will say, Error: Debug Assertion Failed!. Expression: is_block_type_valid(header->_block_use). Can you please tell me what is causing this or show me an example of fixing this issue.
#include <iostream>
using namespace std;
class Myclass
{
public:
void print()
{
cout << "Hello from Myclass" << endl;
}
};
int main()
{
Myclass *obj[3] = { new Myclass, new Myclass, new Myclass };
// Call each object's print function.
for (int index=0; index < 3; index++)
{
obj[index]->print();
}
delete[] obj; //Error
return 0;
}
This:
Myclass *obj[3] = { new Myclass, new Myclass, new Myclass };
is not a dynamically allocated array. It is an array with automatic storage, holding pointers to dynamically allocated objects. To properly clean up, you need:
delete obj[0];
delete obj[1];
delete obj[2];
Because every new must be matched with a delete, and you can only delete via delete[] something that was allocated via new[].
There is no need for any dynamic allocation here, just do:
Myclass obj[3] = {};
The delete[] operator should only be used for arrays created using the new[] operator, which your obj isn't. You have a fixed array of pointers to objects, each of which must be deleted as such:
for (int index=0; index < 3; index++)
{
delete obj[index];
}
Alternatively, you can create your object array using the new[] operator, then delete the array with delete[]:
int main()
{
Myclass* obj = new Myclass[3];
// Call each object's print function.
for (int index = 0; index < 3; index++) {
obj[index].print(); // Note: Use "." here, not "->"
}
delete[] obj;
return 0;
}
The variable obj is declared as an array with automatic storage duration with the element type Myclass *.
Myclass *obj[3] = { new Myclass, new Myclass, new Myclass };
That is it is an array of pointers not a pointer.
Each element of the array is indeed a pointer that points to a dynamically allocated memory. So as the array contains three elements you need to call the operator delete three times for each element.
It is simpler to do that in the range-based for loop.
For example
for ( auto &item : obj )
{
delete item;
item = nullptr;
}
I think you allocated the array wrong.
You should write Myclass* obj = new Myclass[3];
The above answer is perfect.
I would only add this is not a good style code, if you "think in C++". This is a rather C style code.
First of all, when you are coding in C++ and is not obligued to use C-compatible code, be cautious whenever you see yourself using a C pointer.
In this case, if instead of using a C array of C pointers, you had used a std::vector of MyClass objects, the vector destructor would have called your class destructor for each element, which I think is what you wanted.
My suggestion: change the C array to std::vector and you will be happier. Look how you could have implemented it, using C++11 features and forgetting old C stuff:
#include <iostream>
using namespace std;
#include <vector>
class Myclass
{
public:
void print()
{
cout << "Hello from Myclass" << endl;
}
};
int main()
{
cout<<"Hello World" << endl;
vector<Myclass> obj(3);
// Call each object's print function.
for (auto instance : obj)
{
instance.print();
}
return 0;
}
In this case you don't even need to worry about deleting the objects, since the vector destructor will be called when the function goes out of scope, and it will take care of calling Myobjects' destructors. Much cleaner and safer code.
Or, in case performance is a very bottleneck for you and you need a static array, if you are using C++11 or later, you also can use std::array, a less "wild" option (https://en.cppreference.com/w/cpp/container/array).
So that is the tip I leave for you, if coding in C++, use the best this language can offer, and try to forget dangerous and wild old C features. C is good as a lightweight and simpler language, when you need it. But everyone knows it is dangerous (and you have just stumbled on it).
This book of the Bjarne focuses on teaching C++ from scratch, leaving behind the not always productive C legacy:
Programming: Principles and Practice Using C++

Object in map corrupted after retrieving from the map

So I've completely edited my question.
I have a map called mTextMap which contains:
typedef std::map<const std::string, Text*> TextMap;
TextMap mTextMap;
And I have the following methods:
void Foo::setUpGame()
{
Text text(1,2,3,4); //create a Text object
mTextMap["MainText"] = &text; //save it in the map!
}
Text& Foo::getText(const std::string name)
{
auto i= mTextMap.find(name);
return *(i->second); //Gets a reference to the Text that is inside the map
}
Now if I use this way:
Foo foo;
foo.setUpGame();
Text& myText = foo.getText("MainText"); // Why is this corrupted?
The object myText is completely corrupted!!
Why is this happening?
The general problem seems to be, that you think that this line:
mTextMap["MainText"] = &text;
stores the text object in the map. IT DOESN'T! It stores a pointer to the object in the map and the text object itself will - as you said yourself - automatically be destructed at the end of the function. So now your pointer points to a non-existing object, which leads to the observed errors.
There are various solutions to your problem, depending on what exactly, you try to achieve and what you are going to do with your class.
One possibility is to use a map of Text objects (instead of pointers):
typedef std::map<const std::string, Text> TextMap;
void Foo::setUpGame()
{
Text text(1, 2, 3, 4); //create a Text object
mTextMap["MainText"] = text; //copy it into the map!
}
or
void Foo::setUpGame()
{
mTextMap.emplace("MainText", Text(1, 2, 3, 4)); //Doesn't require Text to be default constructable
}
Another possibility is to create the text objects on the heap and use smart pointers (e.g. unique_ptr)
typedef std::map<const std::string, std::unique_ptr<Text>> TextMap;
void Foo::setUpGame()
{
mTextMap["MainText"] = std::make_unique<Text>(1,2,3,4); //create object on the heap an store a pointer to it in the map
}
The std::unique_ptr will automatically destroy the text object, as soon as the map gets destroyed.
If you really need to have a map of raw pointers for some reason, you can use "new" as explained by David, but don't forget to delete them when you don't use them anymore - c++ doesn't have a garbage collector (like e.g. java) that would take care of this automatically.
The "text" object is going out of scope as soon as setUpGame completes. At this point, the heap memory is freed up to be overwritten by any new use of the heap. It is essentially a temporary scratchpad of items that only exists within the scope of a function (or within explicit scope operators inside a function).
David G's advice is sound: read more about the difference between stack and heap memory, and also consider the advice to use smart pointers. However, if you want a cheap, dirty fix to your immediate problem, you can try this:
void Foo::setUpGame()
{
static Text text(1,2,3,4); // Note use of "static" keyword
mTextMap["MainText"] = &text; //save it in the map!
}
Whilst I do not advocate the use of static as a shortcut to solving more fundamental architectural memory issues, you can use this as a short-term measure if you're desperate to get things working. Labeling the object as static ensures its lifetime will outlive the scope of the function. But I would not recommend it as a long-term solution to this kind of issue.
When you dynamically allocate memory for your object, it will live as long as you do not explicitly delete it from memory, it is not deleted after you exit the method it was created in, so you can put a pointer to it in a map and it will always be there (just be sure you delete the memory when removing the object from the map).
You can test this with the following simple code, where I declare a new Int in a function, return a pointer to the memory and print it in the other function that received the map (with the pointer in it). It prints correctly, which means the memory was not freed even when out of scope.
#include <iostream>
#include <map>
std::map<std::string, int*> myMap(){
int* test = new int(1);
std::map<std::string, int*> ObjMap;
ObjMap["object"] = test;
return ObjMap;
}
int main(int argc, const char * argv[]) {
// insert code here...
std::map<std::string, int*> mmap = myMap();
std::cout << *mmap["object"] << std::endl;
return 0;
}
So to answer your question, create your object dynamically like this:
Obj* obj = new obj(1,2,3,4);
And it will not be deleted when out of scope. Still, you need to delete the memory yourself unless you use Smart Pointer, like this: delete obj; (when you remove it from the map, to free the memory as it will not be freed automatically).
PS: You should read on how the Stack and Heap works and how Dynamic and Static allocation works (using the stack OR the heap). See this c++ dynamic memory allocation tutorial to have more informations.
Like MikeMB said, using Smart Pointers is easier as you will be sure you deleted the memory, and you will also be sure you never access a deleted memory. See this Stack Overflow topic for smart pointers informations: What is a smart pointer and when should I use one?

Assignment of string to structure element

My program crashes when I try to assign a string value to a member of a structure.
My suspicion is that the member (of type string) within the structure was never properly allocated in memory.
Here is my code for reference:
#include <string>
#include <sstream>
struct DataRow
{
std::string result;
float temp;
struct DataRow* next;
};
int main( )
{
DataRow* node = (DataRow*)malloc(sizeof(DataRow)); // Allocation of memory for struct here
int currentLoc = 0;
std::string dataLine = "HUUI 16:35:58 54.4 25.1 PDJ 1 MEME PPP PS$% sc3 BoomBoom SuperPower P0 123 25.86 0 11.1 1.0 50.0 W [2.0,0.28] 1.15 [5,6,100]";
std::string dataWord;
std::stringstream sDataLine( dataLine );
while ( sDataLine >> dataWord )
{
if( currentLoc == 0 )
{ node->result = dataWord; } // <-- Problem occurs here
else if ( currentLoc == 3 )
{ node->temp = atof(dataWord.c_str()); } // <-- This code works no problem on it's own
else
{ }
currentLoc++;
}
return 0;
}
The code fails at node->result = dataWord. But if I comment out this if statement, and leave only the node->temp=atof(dataWord.c_str()); the code works no problem.
How do I achieve proper memory allocation for the string member of the DataRow struct?
malloc doesn't ensure any constructors of the members of your struct are called. In C++ struct is basically the same as class, the only difference is that members are public by default rather than private. So you should new the object/struct, and delete it when done.
The way you are allocating node is incorrect: if you want to dynamically allocate non-POD types in C++, you need to use new, since it will call the required constructors (followed by a call to delete when appropriate).
But it might be simpler to allocate an automatic instance:
DataRow node;
If you do need a pointer, make sure to have a look at smart pointers, particularly std::unique_ptr and std::shared_ptr. See also boost::scoped_ptr.
In C++ use 'new' instead of 'malloc'. Using malloc does not run the constructor of your class, so the string is not initialized.
You have to create a new struct and not use malloc at all.
So use:
DataRow* node = new DataRow;
you should also take care of cleaning it up like so:
delete node;
and in case you don't want to allocate it from the heap you can do this as well:
DataRow node;
So before I get to answering your question I just wanted to say that you should not use Malloc in c++ unless you are forced to. This answer explains why fairly well.
In what cases do I use malloc vs new?
With that said changing this line
DataRow* node = (DataRow*)malloc(sizeof(DataRow));
To this
DataRow* node = new DataRow;
Will fix your problem

C++ Template Class

Hey..
I'm having trouble with some homework.
We are working on VectorList ( kinda like linked list but with vectors - don't ask why.. )
Anyway I have something like this:
#ifndef VECTORLIST_H
#define VECTORLIST_H
#include <iostream>
#include <vector>
using namespace std;
template< typename NODETYPE >
class VectorList
{
public:
VectorList(); // constructor
~VectorList(); // destructor
void insertAtFront( const NODETYPE & );
void insertAtBack( const NODETYPE & );
bool removeFromFront( NODETYPE & );
bool removeFromBack( NODETYPE & );
bool isEmpty() const;
void print() const;
private:
vector< NODETYPE > *vList; // list data as a vector
};
I need to fill in the functions.. my problem is that I do not understand how
to use STIL when I have *vList.. its a pointer to the first vector element?
// display contents of VectorList
template< typename NODETYPE >
void VectorList< NODETYPE >::print() const
{
// Fill in the missing code
}
My Idea was to use a for loop on the vector and use cout<< vector[i]<< endl;
to print the vector out..
Problem is that I get all sorts of errors and seg faults.
I do not understand how to access the vector in the function,
and how to access its elements.
This is a header file, and in the main we declare an object of VectorList<NODETYPE> IntVector...
So how can I do this?
Any help with understanding of how this *vList plays a role here would help a lot and
I'd probably be able to finish the rest..
Also, for isEmpty(), I assume I can use vList.empty().. but since vList is a pointer..
it doesn't work quite well.
== For the constructor/destructor what can I do?
I know for destructor I should iterate through the vector and use delete on each element.
But shoul
Please explain this to me, I am frustrated =[
my problem is that I do not understand how to use STL when I
have *vList.. its a pointer to the first vector element?
I assume that you are required as part of your homework to use pointer-to-vector instead of a vector itself. As a rule, I never use pointers-to-containers. In fact, the best thing that I discovered in switching from C to C++ was that I could write entire programs with no pointers at all, thanks to STL programming. Unless you are required to use pointer-to-vector, I recommend that you use the vector directly.
Certainly it is easier to use the vector proper than a pointer, but don't worry. Using the pointer isn't too bad.
First, in order to use a pointer-to-something, one must allocate the something. So, in your constructor, invoke new.
vList = new std::vector<NODETYPE>;
Anytime we invoke new, we must have a matching delete somewhere. Since our new is in our constructor, we need to invoke delete in the destructor:
delete vList;
You said:
but since vList is a pointer.. it doesn't work quite well.
Here is where life gets easy. Generally, if p is a pointer to some type, then (*p) is the object to which p points. Here are some examples:
int i = 1;
int *pInt = &i;
i = 4;
(*pInt) = 4;
std::cout << i << " " << (*pInt) << "\n";
std::vector<NODETYPE> v;
std::vector<NODETYPE> *pVector;
v.push_back();
(*pVector).push_back();
it = v.begin();
it = (*pVector).end();
So, invoking members of vList is easy : (*vList).empty().
So, your code might be :
void insertAtFront(const NODETYPE& node) { (*vList).push_front(node); }
There is a short-cut operator -> that makes the above somewhat easier to read:
void insertAtFront(const NODETYPE& node) { vList->push_front(node); }
The expression x->y is more-or-less equivalent (*x).y.
To sum up:
Allocate your vList in your constructor with new. Destroy your vList in your destructor with delete. Invoke members of vList using either (*vList).function() or vList->function().
Good luck, and come back if you have other questions!
P.s. Since you have a non-trivial destructor, you'll need to consider the rule of three.
P.P.s. You said something about iterating the vector in your destructor and deleting each of the objetcs you find there. You would only need to do that if your data type were vector-of-pointers-to-NODETYPE (contrast to what you declared: pointer-to-vector-of-NODETYPE). Until and unless you become completely comfortable with pointers, I recommend that you never store pointers in STL containers.
You should construct your object in the constructor (if you really need using bare pointers): vList = new vector< NODETYPE >();, free memory in the destructor: delete vList;, translate your methods to corresponding methods of the container class. For example, insertAtBack would be implemented as vList->push_back(elem);

Simple vector program error

Hi iam new to c++ and iam trying out this vector program and i am getting the following error:
error: conversion from test*' to non-scalar typetest' requested|
Here is the code
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
using namespace std;
class test{
string s;
vector <string> v;
public:
void read(){
ifstream in ("c://test.txt");
while(getline(in,s))
{
v.push_back(s);
}
for(int i=0;i<v.size();i++)
{
cout<<v[i]<<"\n";
}
}
};
int main()
{
cout<<"Opening the file to read and displaying on the screen"<<endl;
test t=new test();
t.read();
}
new is used to dynamically allocate memory. You don't need to do that, so just do:
test t; // create an instance of test with automatic storage
t.read(); // invoke a method
The error is because the type of new test() is a test*, a pointer to a (newly created) test. You can't assign a test* to a test.
The pointer version, for what it's worth, would have been:
test* t = new test();
t->read(); // the arrow is short for (*test).
delete t; // don't forget to clean up!
However, it's bad style to do raw memory allocation like that. You'd use something called a smart pointer to make sure it gets deleted automatically, instead. The standard library has one in the header <memory>, called auto_ptr, that would suffice:
std::auto_ptr<test> t(new test()); // put a new test into a pointer wrapper
t->read(); // treat it like a normal pointer
// nothing else to worry about, will be deleted automatically
However, all this isn't needed for you, in this case. Always prefer automatic (stack) allocation over dynamic allocation.
Change
test t=new test();
t.read();
to
test *t=new test();
t->read();
t should be a pointer to type test. And to access a class member using a pointer we use the -> operator. Also its a good practice to delete any dynamically allocated objects as:
delete t;
new test() will return a pointer to a t so you either want to use pointer throuought or create t on the stack
Code using pointers
test *t=new test();
t->read(); // note needs -> rather than .
delete t; // as declared n the heap you must delete
or usually better do all on the stack
test t;
t.read();