I have
class Fred
{
public:
void inspect() const {};
void modify(){};
};
int main()
{
const Fred x = Fred();
Fred* p1;
const Fred** q1 = reinterpret_cast<const Fred**>(&p1);
*q1 = &x;
p1->inspect();
p1->modify();
}
How would it be possible to do the
const Fred** q1 = &p1
via pointer-casting?
(I have just been reading that this might be possible)
Thank you for your answers. The const_cast works indeed for objects
#include <iostream>
#include <stdio.h>
using namespace std;
class Fred
{
int a;
public:
Fred(){};
Fred(int a_input)
{
a = a_input;
};
void inspect() const
{
cout << "Inspect called"<< endl;
cout << "Value is ";
cout << a << endl;
};
void modify()
{
cout << "Modify called" << endl;
a++;
};
};
int main()
{
const Fred x = Fred(7);
const Fred* q1 = &x;
Fred* p1 = const_cast<Fred*>(q1);
p1->inspect();
p1->modify();
p1->inspect();
x.inspect();
*p1 = Fred(10);
p1->inspect();
}
gives
Inspect called
Value is 7
Modify called
Inspect called
Value is 8
Inspect called
Value is 8
Inspect called
Value is 10
Inspect called
Value is 10
However, for predefined types it does not work:
int main()
{
const double a1 = 1.2;
const double* b1 = &a1;
cout << "a1 is " << (*b1) << endl;
cout << "b1 is " << b1 << endl;
double* c1 = const_cast<double*>(&a1);
cout << "b1 is " << b1 << endl;
cout << "c1 is " << c1 << endl;
double* d1 = static_cast<double*>(static_cast<void*>(c1));
cout << "d1 is " << d1 << endl;
cout<< "*d1 is " << *d1 << endl;
*d1=7.3;
cout<< "*d1 is " << *d1 << endl;
cout<< "*d1 address is "<< d1 << endl;
cout << "a1 is " << a1 << endl;
cout << "a1 address is" << &a1 << endl;
cout<< "*d1 is " << *d1 << endl;
cout<< "*d1 address is "<< d1 << endl;
double f1=a1;
printf("f1 is %f \n", f1);
}
is resulting in:
a1 is 1.2
b1 is 0xffbff208
b1 is 0xffbff208
c1 is 0xffbff208
d1 is 0xffbff208
*d1 is 1.2
*d1 is 7.3
*d1 address is 0xffbff208
a1 is 1.2
a1 address is0xffbff208
*d1 is 7.3
*d1 address is 0xffbff208
f1 is 1.200000
Apparently the g++ compiler optimizes such that it replaces a1 by 1.2 whenever it finds it, so, even if its value on the stack has changed, it does not care.
(In my case I had problems with directly reading the *b1, *c1, so I had to do the double static cast - the reinterpret cast did not work).
Is it any way to really change a1, compiling "normally", therefore not compiling without the optimization (so I overtake the optimization effect)?
This should do it:
Foo** f;
const Foo** cf = const_cast<const Foo**>(f);
This is not a good idea, because it violates type safety. Let me explain why:
Fred* pFred;
const Fred** ppFred = const_cast<const Fred**>(&p);
*ppFred = new const Fred; // Now pFred points to a const Fred
pFred->some_evil_mutating_method(); // can do, since type of *pFred is non-const!
You want const_cast.
Why don't you just make:?
const Fred** q1;
*q1 = p1;
Or you want to elide constness violation without const_cast? -- no, sir, you can't.
You should not do it. The fact that you cannot easily do the conversion is because it breaks constant correctness (and your code exercises it). Using the recommendations above your code will compile and will call a mutating method on a constant object (last line of code).
That is not recommended and in some rare cases could even kill your application (a constant global object could be stored in a read-only memory page), or leave it an unstable situation (you change the internal state of an object by changing through a constant reference into an internal member element, breaking the object invariants).
About your problem: C++ FAQ Lite [18.17]
you shouldn't need to do any casting for const Fred** q1 = &p1 as a non-const Fred** can be directly assigned to a const Fred** q1 in its declaration.
Related
I wanted to ask that when I don't write any copy constructor explicitly so the compiler automatically generates the copy constructor which performs shallow copy by default right?
So in the main() program when I changed the values of integers a, b and pointer p only the value of p changed and values of a and b remain unchanged in the copied object. Why the values of a & b didn't change too? My code is:
#include <iostream>
#include <string.h>
using namespace std;
class Dummy {
private:
int a, b;
int *p;
public:
Dummy() {
p = new int;
}
void setData(int x, int y, int z) {
a = x;
b = y;
*p = z;
}
void showData() {
cout << "a = " << a << " b = " << b;
cout << " p = " << *p << endl;
}
~Dummy() {
delete p;
}
};
int main() {
Dummy d1;
d1.setData(3, 4, 5);
Dummy d2 = d1;
d1.showData();
d2.showData();
d1.setData(6, 7, 8);
d1.showData();
d2.showData();
return 0;
}
The output of my program is:
a = 3 b = 4 p = 5
a = 3 b = 4 p = 5
a = 6 b = 7 p = 8
a = 3 b = 4 p = 8
What I'm saying is while the pointer of object d2 changed when I changed the values of object d1 then why didn't the values of a & b of object d2 changed too?
Also I'm using delete keyword in the destructor to delete the dynamically allocated pointer:
~Dummy() {
delete p;
}
But it's crashing my program instead. Why is that?
You've totally got it wrong - The idea of shallow copy. Actually, c++ does not have anything called deep copy built into itself. So, calling something shallow copy is a bit wrong. And just the use of these words shallow copy creates a lot of confusion too.
Now, let me explain, what happens when cpp performs initialization using assignment. cpp or c(while copying struct) has a concept called bitwise copy. In this concept, all the member variables of one object(struct object/class object - you can say either) is identically copied to another object. Now, it's totally wrong idea that, both objects point to same memory location. In actual, both object has their own memory location and of course, their variables occupy different memory spaces. For you, I have write some tests regarding memory. You would understand perfectly, if you just see the test and it's output:
#include <iostream>
#include <string.h>
using namespace std;
class Dummy {
int a, b;
int *p;
public:
Dummy() {
p = new int;
}
void setData(int x, int y, int z) {
a = x;
b = y;
*p = z;
}
void showData() {
cout << "a = " << a << " b = " << b;
cout << " p = " << *p << endl;
cout << endl; // an extra new line for readability of output
}
void showMemory() {
cout << "addr(a) = " << &a << " addr(b) = " << &b;
cout << " addr(p) = " << &p << endl;
}
~Dummy() {
*p = 100;
delete p;
}
};
// testing memory
void memoryTest() {
cout << "testing d1:" << endl;
Dummy d1;
d1.setData(3, 4, 5);
cout << "addr(d1) = " << &d1 << endl;
d1.showMemory();
cout << endl ;
cout << "testing d2:" << endl;
Dummy d2 = d1;
cout << "addr(d2) = " << &d2 << endl;
d2.showMemory();
}
int main() {
// memoryTest
memoryTest();
return 0;
}
And the output of the test was:
testing d1:
addr(d1) = 0x6dfed4
addr(a) = 0x6dfed4 addr(b) = 0x6dfed8 addr(p) = 0x6dfedc
testing d2:
addr(d2) = 0x6dfec8
addr(a) = 0x6dfec8 addr(b) = 0x6dfecc addr(p) = 0x6dfed0
This clearly shows that, the memory occupied by those two objects d1 and d2 are totally different.
Now, you may have another question remain: Then, why, when i write *p=8, it affects both d1 and d2?:
When you assign, Dummy d2 = d1;, we may say something happended like below(though, it's not actually happen when bitwise copy is applied, it's just for clarity):
d2.p = d1.p
So, we know that, d1.p and d2.p contains the same memory location(note: d1.p is a pointer. so, it does not contain any integer, rather it contains memory address of an int).
So, when you write *p = 8, you are telling the program to go to the memory location targeted by p and change the value of that memory location to 8.(note, here, you didn't change the content of d1.p, d1.p still contains the same memory location. rather, you just changed that memory location's content from 5 to 8). That's why when you call d2.p, you get the changed value. cause, d2.p contains the same memory location as d1.p.
Now, there may have one more question: Why your code crashes when you freed p in destructor?:
Now, let me first ask you, can you free a memory what is already freed. You can write the code, but the behavior is undefined. It may crashes your program or it may do nothing.
Well, in Dummy destructor you've written delete p;. Now, either d2 or d1 would be destroyed first. Let's assume, d2 is destroyed first. So, when d2's destroyer is called, p is freed. Then, d1's destroyer will be called and it'll also try to free p. But p is already freed. And in your case, the program meets a crash for this reason.
Hope, everything is clear to you now.
If anything is not clear about what I've described above, then ask questions, I will try my best to answer them too.
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 have few questions regarding below code
#include <iostream>
using namespace std;
class A
{
public:
A & add(A & b);
};
A & A::add(A & z)
{
A * a = new A();
A & b = *a;
cout << "Inside add, address of a: " << &a << endl;
cout << "Inside add, address of b: " << &b << endl;
cout << "Inside add, address of z: " << &z << endl;
A aa;
cout << "Inside, add, address of aa: " << &aa << endl;
return aa;
}
int main()
{
A *a = new A();
cout << "Original a: " << a << endl;
A & b = a->add(*a);
cout << "b: " << &b << endl;
return 0;
}
Q1. Inside main, line 3, a->add(*a), the same object pointed by pointer *a is passed. But inside the function A::add(A &), when i try to achieve the same effect via A &b = *a, i get a different object. Why is this so?
Q2. Inside A::add(A &), i return a non const reference to a local object aa and main gets the same memory address as the local reference. So this has the effect of extending the lifetime of local reference, beyond its scope.
Q3. Inside A::add(A &), i dereference *a multiple times, first via A &b = *a and then by return *a. In both cases, the memory address is always the same. How is this happening? You can check the output of &b inside A::add(A &)and the result of A &b = a->add(*a)
UPDATE:
The issue related to Q1 was that i was doing cout << &a, when i should have been doing cout << a
To eliminate return value optimization, i compiled with -fno-elide-constructors. I am using g++.
A1: You created a new *a with A* a = new A() The a in main is different than the a in A::add. The a in main is referenced by the variable z
A2: No, you created a on the heap, so it is going to last until you call delete on that variable
A3: A dereference does not change the memory location that is stored in the pointer, it just gets the value stored in that location. A reference is more like an alias. So &b is like saying &(*a)
I have problem to understand the behavior of the following code, which I modified from an example for C++ slicing:
#include <stdio.h>
#include <iostream>
struct B {
int x;
B() { x = 0; }
virtual void foo( const char* id ) {
std::cout << id << ": B=" << this << ", x=" << x << std::endl;
}
};
struct D1 : B {
int y;
D1() { x = 1; y = 100; }
virtual void foo( const char* id ) {
std::cout << id << ": D1=" << this << ", x=" << x << ", y=" << y << std::endl;
}
} d1;
struct D2 : B {
int z;
D2() { x = 2; z = 200; }
virtual void foo( const char* id ) {
std::cout << id << ": D2=" << this << ", x=" << x << ", z=" << z << std::endl;
}
} d2;
void main() {
std::cout << "d1 = " << &d1 << std::endl;
std::cout << "d2 = " << &d2 << std::endl;
std::cout << "By pointer at beginning: " << std::endl;
B* pb = &d1;
pb->foo( "pd1" );
pb = &d2;
pb->foo( "pd2" );
std::cout << "By Value: " << std::endl;
B b = d1;
b.foo( "d1" );
b = d2;
b.foo( "d2" );
std::cout << "By pointer after by value: " << std::endl;
pb = &d1;
pb->foo( "pd1" );
pb = &d2;
pb->foo( "pd2" );
std::cout << "By reference: " << std::endl;
B& rb = d1;
rb.foo( "rd1" );
rb = d2;
rb.foo( "rd2" );
std::cout << "By pointer after by reference: " << std::endl;
pb = &d1;
pb->foo( "pd1" );
pb = &d2;
pb->foo( "pd2" );
}
//The result is the following:
d1 = 0115B504
d2 = 0115B510
By pointer at beginning:
pd1: D1=0115B504, x=1, y=100
pd2: D2=0115B510, x=2, z=200
By Value:
d1: B=0036FE44, x=1
d2: B=0036FE44, x=2
By pointer after by value:
pd1: D1=0115B504, x=1, y=100
pd2: D2=0115B510, x=2, z=200
By reference:
rd1: D1=0115B504, x=1, y=100
rd2: D1=0115B504, x=2, y=100
By pointer after by reference:
pd1: D1=0115B504, x=2, y=100
pd2: D2=0115B510, x=2, z=200
From the above result, we can see that:
Value assignment causes slicing problem to the assign destination (b) by dropping the derived specific members, but leave the assign sources (d1 and d2) intact.
Reference assignment causes slicing to the assign destination (rd) by not assigning the derived specific members, thus partially changes the assign sources (d1 and d2).
At first, I was surprised that you can assign a reference to a different type (D2 to D1) via their base, until I realize the infamous C++ casting system. One conclusion seems that reference can only be initialized but not assigned.
We know that STL container for base object has slice problem because except list, all other STL container copy object around. It looks that STL container for base references should fair no better, unless it saves pointers inside.
How do you guys deal with this problem?
Thanks!
CP
I'm finding it hard to find a question in your text, but I'm going to assume it is something like:
"How do I polymorphically store objects in a standard container?"
First, let me just say that you can't store references in standard containers because you can't assign (rebind) them.
So the normal way is to have a container of base class pointers. If the container owns the items, then use smart pointers like unique_ptr or shared_ptr. If the container does not own the objects, then just use raw pointers.
B& rb = d1;
rb.foo( "rd1" );
rb = d2;
The last line is equivalent as if you wrote
d1 = d2;
except it applies only to base class subobject. In the first line you set up the reference creating rb as alias to d1 with different static type. The reference can not be reseated. The later assign targets the object. d1 directly could only be assigned with using trickery with its op=, but your changed static type makes Base::op= work.
Many mentors say you should only use abstract classes as base, and most of the reasoning points to accidents like this.
In hierarchies you rarely have the op= left, if absolutely needed you have some virtual ssign thing that verifies compatibility.
In book named "Using C++" by Rob McGregor there is following example of using pointer-to-member operator
class mycls
{
public:
int member;
int *ptr;
};
void main()
{
mycls MyClass;
// Derive a pointer type to the non-pointer class member
int mycls::*member = &mycls::member;
MyClass.ptr = new int;
mycls* pMyClass = &MyClass;
pMyClass->*member = 5;
*MyClass.ptr = 10;
cout << "pMyClass->*member = " << pMyClass->*member << "\n"; // pMyClass->*member = 5
cout << "MyClass.*member = " << MyClass.*member << "\n"; // MyClass.*member = 5
cout << "*MyClass.ptr = " << *MyClass.ptr << "\n"; // *MyClass.ptr = 10
cout << "*pMyClass->ptr = " << *pMyClass->ptr << "\n"; // *pMyClass->ptr = 10
delete MyClass.ptr;
}
In this example I don't understand why member variable mycls::member becomes maybe a pointer after (guessing) this line of code:
int mycls::*member = &mycls::member;
What this does?
Suppose you had a local variable:
int member;
You could make a pointer to it with:
int *ptr = &member;
To get the pointer to member syntax, we just append mycls:: in the appropriate places:
int mycls::*member = &mycls::member;
It might be clearer with an example that shows how the pointer can switch between any members of the class that are of the correct type:
class C
{
public:
int a;
int b;
};
void main()
{
// make pointer to member, initially pointing to a
int C::*ptrToMember = &C::a;
C x;
C *ptrToObj = &x; // make pointer to object x
ptrToObj->*ptrToMember = 2; // store in a;
ptrToMember = &C::b; // change pointer to b
ptrToObj->*ptrToMember = 3; // store in b;
}
Note how we create the pointer to the member a before we've created an object of type C. It's only a pointer to a member, not a pointer to the member of a specific object. In the 'store' steps, we have to say which object as well as which member.
Update
In the comments the OP asked if this is the same:
int *ptr = &(ptrToObj->a);
No, it's not. That is a pointer to any int, anywhere in memory.
The easiest way to understand this is to think of what it means technically. A "pointer" is an absolute location in memory: where to find an object. A "pointer-to-member" is a relative location, sometimes called an offset: where to find an object within the storage of an outer object. Internally they are just numbers. A pointer-to-member has to be added to an ordinary pointer to make another pointer.
So if you have a pointer to an object (an int is an object!), you can use it to change what is stored at that absolute location in memory:
*ptr = 123;
But if you have a pointer-to-member, it is not a memory location. It is an offset, an amount to be added to a memory location. You cannot use it by itself. You must "add" it to an object pointer:
ptrToObj->*ptrToMember = 132;
This means: go to the location in memory ptrToObj, then move along by the distance ptrToMember.
He called the class member member and the pointer-to-member member, confusing the issue. Does renaming them like this help?
Class:
class SampleClass
{
public:
int m_data;
int* m_pointer;
};
Usage:
int main()
{
SampleClass sample;
// Derive a pointer type to the non-pointer class member
int SampleClass::*pointerToMember = &SampleClass::m_data;
sample.m_pointer = new int;
SampleClass* pSample = &sample;
pSample->*pointerToMember = 5;
*sample.m_pointer = 10;
// pSample->*pointerToMember = 5
cout << "pSample->*pointerToMember = "
<< pSample->*pointerToMember << "\n";
// sample.*pointerToMember = 5
cout << "sample.*pointerToMember = "
<< sample.*pointerToMember << "\n";
// *sample.m_pointer = 10
cout << "*sample.m_pointer = "
<< *sample.m_pointer << "\n";
// *pSample->m_pointer = 10
cout << "*pSample->m_pointer = "
<< *pSample->m_pointer << "\n";
delete sample.m_pointer;
}
[Code]
Edit: Re "I'm still currious whether int *ptr = &(ptrToObj->a); is the same as using pointer to a member like in the book":
It's not a pointer-to-member. It is just a normal pointer to memory that happens to be in an object.
You can see the syntax in use here:
Class:
class C
{
public:
int a;
int b;
};
Usage:
int main()
{
// make pointer to member, initially pointing to a
int C::*ptrToMember = &C::a;
C x = {10, 11};
C *ptrToObj = &x; // make pointer to object x
cout << "a initial value: " << ptrToObj->*ptrToMember << endl;
ptrToObj->*ptrToMember = 2; // store in a;
cout << "a after change: " << ptrToObj->*ptrToMember << endl;
ptrToMember = &C::b; // change pointer to b
cout << "b initial value: " << ptrToObj->*ptrToMember << endl;
ptrToObj->*ptrToMember = 3; // store in b;
cout << "b after change: " << ptrToObj->*ptrToMember << endl;
int* ptr = &(ptrToObj->a);
cout << "ptr to a: " << *ptr << endl;
ptr = &(ptrToObj->b);
cout << "ptr to b: " << *ptr << endl;
}
[Code]
The asterisk character in the declaration is part of the type.
Your declaration breaks down into
Type: int mycls::*
Variable name: member
Initialiser: = &mycls::member
This new variable member points is a member pointer to an int held in a mycls. It doesn't have to point to a mycls::member.