Following results are very interesting and I am having difficulty understanding them. Basically I have a class which has an int:
class TestClass{
public:
int test;
TestClass() { test = 0; };
TestClass(int _test) { test = _test; };
~TestClass() { /*do nothing*/ };
};
A test function which accepts a pointer of TestClass
void testFunction1(TestClass *ref){
delete ref;
TestClass *locTest = new TestClass();
ref = locTest;
ref->test = 2;
cout << "test in testFunction1: " << ref->test << endl;
}
This is what I am doing in main:
int main(int argc, _TCHAR* argv[])
{
TestClass *testObj = new TestClass(1);
cout << "test before: " << testObj->test << endl;
testFunction1(testObj);
cout << "test after: " << testObj->test << endl;
return 0;
}
I was expecting output to be:
test before: 1
test in testFunction1: 2
test after: 1
But I get the following output:
test before: 1
test in testFunction1: 2
test after: 2
Can someone explain this. Interesting thing is that changing testFunction1 to:
void testFunction1(TestClass *ref){
//delete ref;
TestClass *locTest = new TestClass();
ref = locTest;
ref->test = 2;
cout << "test in testFunction1: " << ref->test << endl;
}
i.e. I do not delete ref before pointing it to new location, I get the following output:
test before: 1
test in testFunction1: 2
test after: 1
I would really appreciate if someone can explain me this strange behavior. Thanks.
When you access the object after deleting it, the behaviour is undefined.
The behaviour that you see follows from the memory allocation algorithm in your system.
That is after deleting your first testclass object, you allocate memory for a new object. The runtime simply reuses the memory.
To check what is going on, print the values of the pointers:
void testFunction1(TestClass *ref){
cout << ref << endl;
delete ref;
TestClass *locTest = new TestClass();
cout << locTest << endl;
ref = locTest;
ref->test = 2;
cout << "test in testFunction1: " << ref->test << endl;
}
You get a copy of the pointer to the object in testFunction1(), so when you assign to it, the original value of the pointer in main() does not change
Also, you are deleting the object (by calling delete in testFunction1()) to which the original pointer (in main()) is pointing, but as the value in main() is not updated, you are accessing an invalid object -- the fact that you can read the value that you set in testFunction1(), is a coincidence and cannot be relied on
The fact that you correctly read the original value in the second case (when you don't call delete) is because the original object has not been changed (you change a new one in testFinction1 and the pointer to it in main is the same (as explained above) and the object is still alive
in this case , you just got the new object at the same address with the old one you delete.
actually testObj became a dangling pointer after you call testFunction1.
void testFunction1(TestClass *ref){
delete ref;
TestClass *locTest = new TestClass();
cout << "locTest = " << locTest << endl;
ref = locTest;
ref->test = 2;
cout << "test in testFunction1: " << ref->test << endl;
}
int main(int argc, char * argv[])
{
TestClass *testObj = new TestClass(1);
cout << "test before: " << testObj->test << endl;
cout << "testObg = " << testObj << endl;
testFunction1(testObj);
cout << "test after: " << testObj->test << endl;
cout << "testObg = " << testObj << endl;
return 0;
}
Output is :
test before: 1
testObg = 0x511818
locTest = 0x511818
test in testFunction1: 2
test after: 2
testObg = 0x511818
After this instruction:
TestClass *testObj = new TestClass(1);
you have allocated a new memory area containing a TestClass object, whose address (let's call it maddr) is stored into testObj.
Now, this instruction:
cout << "test before: " << testObj->test << endl;
outputs 1, as expected.
Inside testFunction1() you have a local variable called ref, which is a pointer containing the value maddr.
When you delete ref, you deallocate the area of memory containing a TestClass object, whose address is maddr.
Then you allocate a new memory area:
TestClass *locTest = new TestClass();
and locTest contains its address, let's call it m1addr.
Then you use ref to access the memory area at m1addr and change the int test value to 2.
This instruction:
cout << "test in testFunction1: " << ref->test << endl;
outputs 2 as expected.
Now, back to main, you have lost any handler to the area containing a TestClass object whose address is m1addr (that is, you are leaking memory) and the area pointed to by testObj is not allocated anymore.
When you use testObj again, you access an area of memory starting at maddr, which has been cleaned. The effect of accessing testObj->test is undefined behavior.
What you experience could be do to the fact that when you run your code maddr == m1addr, but this can only happen by chance, you cannot rely on this.
Odds are the new object (with a 2) is being created where the old deleted object (with a 1) used to be. Your original pointer still points to that location so when you access it you accidentally access the new object (with a 2).
TestClass *ref in the parameter to testFunction1 and TestClass *testObj in main are 2 different pointers to the same thing, they are not the same pointer though. If you want to delete and reallocate an object inside a function/method you can use a pointer to a pointer as the parameter.
As others have mentioned , after testfunction1 you're accessing an object that was deleted within testfunction1 which as also mentioned is undefined behaviour. The memory being pointed to by the dangling pointer was released during the delete but the contents are likely to still be there until the memory location is reallocated during another call to new. So you are using unallocated space that could be overwritten very easily at anytime.
Hope this helps
Related
I am the following code
struct Me {
Me(Me* a) { std::cout << "Processing " << a << std::endl; }
};
int main() {
Me a(&a);
std::cout << "Created obj in " << &a << std::endl;
Me* ak = new Me(ak);
std::cout << "Created obj in " << ak << std::endl;
delete ak;
return 0;
}
and the output was
Processing 0x7ffdbd7f0607
Created obj in 0x7ffdbd7f0607
Processing 0x5653b66b5110
Created obj in 0x5653b6d35120
As you can observe that first 2 line of output was fine as the address passed to the constructor is same as the object being created but why can't same be done with dynamic creation. Can someone provide a description with possible solution for this?
In Me a(&a); it takes an address of uninitialised variable a. The address is valid, but the object at that address doesn't exists yet. The object is considered existing once the constructor function is entered.
In Me* ak = new Me(ak); ak is not initialized unit after Me constructor returns. That results in passing an indeterminate value of ak into Me constructor.
Can someone provide a description with possible solution for this?
The solution for that is this:
struct Me {
Me() { std::cout << "Processing " << this << std::endl; }
};
See this pointer for full details.
I have two classes, let's call them A and B
class A:
{
public:
//Some functions
A *getNewA() const;
private:
//some attributes
}
class B:
{
public:
//Some functions
private:
A &reftoA;
}
In the main code, I must generate a new A thanks to the A::getNewA() method. And this must go to B::reftoA, as written in class B.
Here is the A::getNewA() method :
A *A::getNewA()
{
A *newA = new A;
return newA;
}
OK. So now I call getNewA and want to store the results in reftoA, which is a reference to A. In a B function (which take a reference to A as parameter)
B::foo(A ¶mA)
{
reftoA = *(paramA.getNewA());
}
I thought this should have been working, but it won't.
Because when dereferencing, reftoA will always take the this object and not the new allocated object.
Let's be clearer and let's modify the functions to output the results
A * A::getNewA()
{
A *newA = new A;
std::cout << "New pointer " << newA << std::endl;
std::cout << "this pointer" << this << std::endl;
return A;
}
void B::foo(A ¶mA)
{
reftoA = *(paramA.getNewA());
std::cout << "new generated pointer " << &reftoA << std::endl;
}
Here is one of the output :
New pointer : 004FFAEC
this pointer: 0069D888
New generated pointer : 0069D888 //Expected : 004FFAEC
I can't get this "new generated pointer" to be the same than the new pointer the A::getNewA() returns after having allocated the memory. Of course, I guess there is some point with dereferencing the pointer to store it in a reference.
I know reference are used with existing object. Maybe the new object A::getNewA() should allocate memory for won't work as I expected.
I could use pointer instead reference in B::foo(), I know, but I can't
I think I am misunderstanding something about refrence and pointer, but I don't know what.
Any help greatly appreciated
The problem is that you can not reassign a reference. You can change only the value of the referenced object.
So you have to initialize the reference in the initializer list of the constructor of the class B.
Take into account that there is a typo in your code snippet
A*A::getNewA()
{
A *newA = new A;
std::cout << "New pointer " << newA << std::endl;
std::cout << "this pointer" << this << std::endl;
return A;
^^^^^^^^^
}
I think you mean
A*A::getNewA() const
^^^^^
{
A *newA = new A;
std::cout << "New pointer " << newA << std::endl;
std::cout << "this pointer" << this << std::endl;
return newA;
^^^^^^^^^^^
}
Always try to provide a verifiable complete example.
Here is a demonstrative program
#include <iostream>
class A
{
public :
//Some functions
A* getNewA() const
{
A *newA = new A;
std::cout << "New pointer " << newA << std::endl;
std::cout << "this pointer" << this << std::endl;
return newA;
}
private :
//some attributes
};
class B
{
public :
B( const A& a ) : reftoA( *a.getNewA() )
{
std::cout << "&reftoA " << &reftoA << std::endl;
}
private :
A& reftoA;
};
int main()
{
A a;
B b( a );
return 0;
}
Its output is
New pointer 0x2b392afbec20
this pointer0x7ffd287ad0af
&reftoA 0x2b392afbec20
As you can see the values of the New pointer and &reftoA are equal each other.
To make it more clear consider a very simple example
#include <iostream>
int main()
{
int x = 10;
int y = 20;
int &r = x;
r = y;
std::cout << "x = " << x << std::endl;
std::cout << "y = " << y << std::endl;
std::cout << "r = " << r << std::endl;
std::cout << std::endl;
std::cout << "&x = " << &x << std::endl;
std::cout << "&y = " << &y << std::endl;
std::cout << "&r = " << &r << std::endl;
return 0;
}
The program output is
x = 20
y = 20
r = 20
&x = 0x7ffd88ad47a8
&y = 0x7ffd88ad47ac
&r = 0x7ffd88ad47a8
This statement
r = y;
did not force the reference to refer the object y. It just reassigned the value of the referenced object x.
References have to be initialized when they are created.
Yes, you are misunderstanding something.
getNewA() is returning a pointer. it's not a smart pointer, you want to look into those and that's all I'll say on the matter.
on returning a pointer, you must keep a reference to this pointer else you will be unable to delete it and you'll get a memory leak. Thus you MUST have somewhere A* a = A::getNewA() and then later, when you no longer need it delete a;
Where you need to pass a reference to A, you can do foo(*a) which will dereference the pointer and pass a reference to the object it's pointing to.
But in summary, for all new code, smart pointers; there's no excuse to not use them.
Side note: Your code example had a few other issues; such as getNewA wasn't static; I'm going to take the code as a working example of your understanding, and not a working example.
Edit: On re-reading your example, the getNewA is intentionally non-static. I think this question is actually an XY problem (ie you're asking a question you've forced yourself into but isn't your actual problem); but I hope this addresses your misunderstanding of pointers and references.
You are not returning the pointer in the getNewA-Method
A* A::getNewA()
{
A *newA = new A;
return A; // you are returning A and not newA
}
And if you want to reassign the reference to a you can use a std::reference_wrapper
class B :
{
public :
void foo(A& paramA) {
reftoA = *(paramA.getNewA());
}
private :
std::reference_wrapper<A> reftoA;
}
I encountered a problem which I am baffled with. This pertains to whether I choose to store an object, or a pointer to it.
This is my class:
class Test {
public:
std::string abc;
int x;
Test(std::string def, int y) {
abc = def;
cout << abc << endl; //THIS ALWAYS GIVES "ghi"
x = y;
}
};
Storing it as a pointer:
Test* T1 = &Test{ "ghi", 100 };
cout << T1->abc << endl; //**THIS IS BLANK -- WHY!?**
cout << T1->x << endl; //THIS GIVES 100
Storing it as an object itself:
Test T2 = Test{ "ghi", 100 };
cout << T2.abc << endl; //THIS GIVES "ghi"
cout << T2.x << endl; //THIS GIVES 100
I'm relatively new to C++ but based on my understanding, T1->abc should dereference the pointer T1 (and therefore I have a Test object), and then access the member abc of that Test object. Since I already created the object, it should be "ghi". But this gives blank instead.
Apparently, this applies only to the string member and not the integer member, as T1->x works fine.
And the problem doesn't exist when I store the object instead of a pointer to it, as shown by the object T2.
I have checked that during construction of T1 and T2, abc is always "ghi" inside the constructor. Somehow, after construction, the string just disappears.
Also, based on what I read, abc = def copies the string content and not the pointer, so it probably isn't a scope issue.
https://msdn.microsoft.com/en-us/library/b930c881.aspx makes it very clear that in either case, whether -> or . is used, assignment can be made.
Searching Google and stackoverflow did not help. Hence yours appreciated. Thanks in advance.
class Test {
public:
std::string abc;
int x;
Test(std::string def, int y) {
abc = def;
x = y;
}
};
int main() {
Test* T1 = &Test{ "ghi", 100 };
cout << T1->abc << endl; //THIS IS BLANK -- WHY!?
cout << T1->x << endl; //THIS GIVES 100
Test T2 = Test{ "ghi", 100 };
cout << T2.abc << endl; //THIS GIVES "ghi"
cout << T2.x << endl; //THIS GIVES 100
return 0;
}
This construct:
Test{ "ghi", 100 };
creates temporary variable, that you are trying to point to. This is just wrong.
If you want to store it using pointer:
Test* T1 = new Test{ "ghi", 100 };
cout << T1->abc << endl; //This is not blank anymore
cout << T1->x << endl;
delete T1; //Do NOT forget this!
By the way, if you are wondering, why this line:
cout << T1->x << endl;
was still evaluating to 100: when object is destroyed, all its members are also destroyed (in terms of calling their destructors). Since x is an int, its destructor in no-op and content of memory occupied by it does not change.
On the other hand, abc is and std::string, which frees allocated memory during destruction - so T1->abc was referring to an empty string.
Test* T1 = &Test{ "ghi", 100 };
The temporary rvalue of Test{ "ghi", 100 } immediately goes out of scope and ceases to exist after this statement.
Thus dereferencing it like
cout << T1->abc << endl;
simply calls Undefned Behavior on a dangling pointer.
This code snippet
Test* T1 = &Test{ "ghi", 100 };
cout << T1->abc << endl; //**THIS IS BLANK -- WHY!?**
cout << T1->x << endl; //THIS GIVES 100
has undefined behaviour because after statement
Test* T1 = &Test{ "ghi", 100 };
temporary object Test{ "ghi", 100 } will be deleted and the pointer becomes invalid.
A valid code could look the following way
Test* T1 = new Test{ "ghi", 100 };
cout << T1->abc << endl;
cout << T1->x << endl;
delete T1;
Or instead of the pointer you could use a constant reference to the temporary object. For example
const Test &T1 = Test{ "ghi", 100 };
cout << T1.abc << endl;
cout << T1.x << endl;
The temporary object will be alive while the reference will be alive.
Test* T1 = &Test{ "ghi", 100 };
Please don't do this. This is exactly what's causing your problem. Instead use
Test* T1 = new Test("ghi", 100);
Because the first way created a reference to a temporary object, which disappears before you try to get the string for printing.
It works for the non-pointer because you're giving the temporary object to a new object.
don't remember to delete (because you've used new)
delete T1;
Or, as πάντα ῥεῖ pointed out, what would be safer, and better c++ coding practice, would be to use a smart pointer. The most relevant one that comes to mind is unique_ptr.
std::unique_ptr<Test> T1(new Test());
std::cout << T1->abc << std::endl;
...
I have a question regarding the following code, which crashes. I am creating a local variable in testfunction() and then pushing it (variable "y") into a list. This variable has a member pointer "b" of object type Ball. As I understand, this local variable "y" is on the stack, so its' destructor will be called after testfunction() is completed. Also, as I understand, a vector "copies" an object into its' list. From what I've learned, it is best practice to delete a pointer in the destructor if one exists in its' class. So, there is "delete b" in the destructor of Example.
The issue that I am having is that the object y.b is being destroyed at the completion of testfunction(). In main(), I am able to see the value of "name" and the address of "b", but the object "b" has already been deleted. I would like to avoid this.
I think there is an issue with the design of the code/use of pointers vs references, etc. Please guide me in the right direction, I am an idiot!
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Ball
{
public:
int a;
Ball()
{
a = 0;
}
~Ball()
{
cout << "destroyed Ball()" << endl;
}
};
class Example
{
public:
string name;
Ball* b;
Example()
{
name = "";
b = NULL;
}
~Example()
{
cout << "destroying Example()" << endl;
delete b;
}
};
void testfunction(vector<Example>& list)
{
cout << "entered testfunction1()" << endl;
Example y;
y.name = "myName";
y.b = new Ball();
y.b->a = 5;
cout << "y.b->a = " << y.b->a << endl;
list.push_back(y);
cout << "exit testfunction1()" << endl;
}
void testfunction2()
{
cout << "entered testfunction2()" << endl;
Example* y = new Example();
cout << "exit testfunction2()" << endl;
}
int main() {
vector<Example> list;
testfunction(list);
//testfunction2();
if(list[0].b == NULL)
cout << "b is null" << endl;
else
cout << "b is not null" << endl;
cout << list[0].name << endl;
cout << list[0].b << endl;
cout << "list[0].b->a = " << list[0].b->a << endl;
return 0;
}
Since class Example has a pointer member and it tries to own a dynamically allocated resource, it needs non-default copy operations, in other words, it needs user-defined copy constructor and assignment operator.
Inside testfunction, when you copy y into vector, both local y and y copied to the vector point to very same Ball object. The local y is destroyed at the end of the function and Ball is deleted. However, that deleted Ball still pointed by the y in vector
void testfunction(vector<Example>& list)
{
// ...
Example y;
y.name = "myName";
y.b = new Ball();
y.b->a = 5;
list.push_back(y);
// ...
} // <-- destructor for Example y is called and y.b is deleted
Define a copy constructor and an assignement operator for your class Example.
These shall copy properly your object (creating a duplicated Ball object) when pushed back on the vector.
Example(const Example& a)
{
name = a.name; // attention no dynamic allocation
cout << "copy" <<endl;
if (a.b) {
b = new Ball(*a.b); // create a new duplicated Ball
}
else b = NULL;
}
The problem in your example is that the default copy constructor is called when you pushback the object. It copies memberwise and so the pointer to Ball is copied, not the object pointed to.
Yet another alternative could be to replace your Ball* with shared_ptr<Ball> (and accordingly, new Ball with make_shared<Ball>() and the delete b of the object with a b.reset()). The principle is that this smart pointer keeps track of the number of time the object pointed to is used, so that it will not delete it twice, but only when its no longer used anywhere.
I am trying to get a grasp on pointers and their awesomeness as well as a better C++ understanding. I don't know why this wont compile. Please tell me what is wrong? I'm trying to initialize the pointer when an instance of the class is created. If I try with a normal int it works fine but when I tried to set it up with a pointer i get this in the console
Running…
Constructor called
Program received signal: “EXC_BAD_ACCESS”.
sharedlibrary apply-load-rules all
Any assistance is appreciated greatly.
Here is the code
#include <iostream>
using namespace std;
class Agents
{
public:
Agents();
~Agents();
int getTenure();
void setTenure(int tenure);
private:
int * itsTenure;
};
Agents::Agents()
{
cout << "Constructor called \n";
*itsTenure = 0;
}
Agents::~Agents()
{
cout << "Destructor called \n";
}
int Agents::getTenure()
{
return *itsTenure;
}
void Agents::setTenure(int tenure)
{
*itsTenure = tenure;
}
int main()
{
Agents wilson;
cout << "This employees been here " << wilson.getTenure() << " years.\n";
wilson.setTenure(5);
cout << "My mistake they have been here " << wilson.getTenure() <<
" years. Yep the class worked with pointers.\n";
return 0;
}
You don't ever create the int that the pointer points to, so the pointer is pointer to an area of memory that doesn't exist (or is used for something else).
You can use new to get a block of memory from the heap, new returns the address of the memory location.
itsTenure = new int;
So now itsTenure holds the memory location you can dereference it to set its value.
The changed constructor is as follows:
Agents::Agents()
{
cout << "Constructor called \n";
itsTenure = new int;
*itsTenure = 0;
}
But you must also remember to delete it using delete
Agents::~Agents()
{
cout << "Destructor called \n";
delete itsTenure;
}
You are just missing a new, in the constructor.
itsTenure = new int;
You don't need to make this a pointer, however. Why are you?
You have to allocate a block of memory for your int, and only then use the address of this block of memory (the pointer). This is done with new :
cout << "Destructor called \n";
itsTenure = new int;
*itsTenure = 0;
Then you have to release the memory in the destructor with delete:
cout << "Destructor called \n";
delete itsTenur;
*itsTenure = 0 does not initialize the pointer. It writes 0 to the location that itsTenure points to. Since you never specified where itsTenure points to, that might be anywhere and the behaviour is undefined (an access violation like you're getting being the most likely result).
You need to allocate memory for *tenure in the constructor:
Agents::Agents()
{
cout << "Constructor called \n";
itsTenure = new int;
*itsTenure = 0;
}