This question already has answers here:
What will happen when I call a member function on a NULL object pointer? [duplicate]
(6 answers)
Closed 4 years ago.
#include<iostream>
using namespace std;
class Child {
public:
int b;
void gotoSchool() {
cout << "going to school";
}
};
int main( )
{
int a;
Child *p2 = (Child *) &a; // #2
p2->gotoSchool();
return 0;
}
The output of this code is
going to school
but how is this working? How can an integer be typecasted to a user-defined class? Explain to me the concept behind this scenario, please.
What you are doing there is just casting an address and not an integer. For your computer an integer is a serie of bytes (4 bytes in a 32bits processor), let's put it a value of 8. This integer has an address (4 bytes in a 32bits processor too), let's say that the value of that address is 1.
In your code you are casting the address of a. So, pointer p2 has its address. A pointer is an address by definition. The arguments that your class "Child" will take in the casting are the byte values after "a" until it fills its data. In this case, the data is a single int, so the value of "a" and the value of Child "b" is going to be the same one. A pointer as it is just a memory address can be whatever type (consider a class a type you want). The type only tells to the pointer what is the size of the data, and how to interpret it. Now you have been unlucky and the type fits perfectly with the integer. But usually the behaviour of such casting is unespected.
I have modified your code in order to ilustrate what is happening, I think you will see it much more clear after executing it
#include<iostream>
using namespace std;
class Child {
public:
float b;
Child(){ b = -0.5;};
void gotoSchool(){
cout<<"going to school" << endl;}
void changeValue(){ b = -0.5;};
void displayB()
{
cout << "the value of b is " << b << endl;
};
};
class OriginalChild {
public:
int b;
void gotoSchool(){
cout<<"going to school";}
};
int main( )
{
int a = 8;
Child *p2 = (Child *) &a; // #2
OriginalChild *p3 = (OriginalChild *) &a;
p2->gotoSchool();
cout << a << endl;
p2->displayB();
cout << p3->b << endl;
p2->changeValue();
cout << a << endl;
return 0;
}
Related
I am experimenting with Pointers and can't figure out why this won't work.
I know that I am supposed to be using STL containers instead of using raw pointers but I am curious as to why this is not working.
Suppose that we have a class like this
class Example
{
public:
Example()
:number{10}
{
std::cout << "From Example Class " << std::endl;
}
~Example()
{
std::cout << "Destructor from Example Class" << std::endl;
}
void print()
{
std::cout << "Number from Example : " << number << std::endl;
}
private:
int number{};
};
We initialize a pointer to array of pointers like this
// Pointer to array of pointers
Example** ex_ptr_array{ new Example * [4] };
for (size_t i = 0; i < 4; i++)
{
ex_ptr_array[i] = new Example{};
}
I can dereference a pointer by doing this and I can call the objects method without using -> operator.
(*ex_ptr_array[0]).print();
// Prints Number from Example : 10
I can also use the array style and use -> operator to call the objects method.
ex_ptr_array[2]->print();
// Prints Number from Example : 10
But I dont understand why the Pointer Arithmetic will not work
// Why doesnt this work?
(*ex_ptr_array + 1)->print();
// Prints some random value
// Number from Example : -33686019
(*ex_ptr_array + 1)->print();
You're dereferencing ex_ptr-array first, and then adding one. Do it the arithmetic before the dereference:
(*(ex_ptr_array + 1))->print();
The compiler knows the size of the type held in ex_ptr_array, so when you add 1 to the pointer, it actually increments the pointer by the size of that type.
When initializing a pointer to allocate memory in the heap, should we specify the type as a pointer? That is, should it be:
int* ptr = new num;
OR
ptr = new num;
Both seem to work, and I was under the impression that the first method is better, but doing it is causing some issues in my code below.
I have a class with two member variables, both of which should be pointers to a new int on the heap. When the copy constructor is invoked, it should allocate new memory in the heap, but copy the values of the ints to which the pointers of the argument being passed in are pointing.
#include <iostream>
using namespace std;
// Header file
#pragma once
class numPair {
public:
int *pa,*pb;
numPair(int, int);
numPair(const numPair &);
};
// Implementation file
#include "Cube.h"
#include <iostream>
using namespace std;
numPair::numPair(int a, int b) {
cout << "Constructor invoked!" << endl;
int* pa = new int(a);
cout << "pa = " << pa << endl;
cout << "*pa = " << *pa << endl;
int* pb = new int(b);
cout << "pb = " << pb << endl;
cout << "*pb = " << *pb << endl;
}
numPair::numPair(const numPair& other) {
cout << "Copy invoked!" << endl;
int* ptr = other.pa;
cout << "ptr in copy: " << ptr << endl;
}
// main.cpp file
#include "Cube.h"
#include <iostream>
using namespace std;
int main() {
numPair p(15,16);
cout << "p.pa = " << p.pa << endl;
numPair q(p);
numPair *hp = new numPair(23, 42);
delete hp;
return 0;
}
The output of the main.cpp file is:
Constructor invoked!
pa = 0x5594991a7280
*pa = 15
pb = 0x5594991a72a0
*pb = 16
p.pa = 0x3
Copy invoked!
ptr in copy: 0x3
Constructor invoked!
pa = 0x5594991a72e0
*pa = 23
pb = 0x5594991a7300
*pb = 42
As can be seen, when the constructor is invoked, the pa and pb are both valid memory addresses to ints holding the values 15 and 16. However, once the constructor has finished executing, if I try to access the value of p.pa, it returns 0x3, instead of the memory address from before. This is, of course, a problem on its own and also leads to issues with the copy constructor.
I've found two ways of fixing this.
The first is to change the definition of the constructor by removing the type of pa and pb. That is changing int* pa = new int(a); to pa = new int(b). Repeat the same for pb. Now, p.pa returns the correct memory address.
The second is by commenting out the initialisation and deletion of hp. That is, removing these lines from the main() function:
numPair *hp = new numPair(23, 42);
delete hp;
I don't really understand why specifying the type of a pointer is causing these errors or, in fact, why the memory addresses for p.pa and p.pb are having errors because of the initialization of another instance of the class, especially when considering the fact that hp is initialized after p.
The short answer is that you are misunderstanding the distinction between locally scoped variables and class members. One way to think about this is that you only need to tell your program the type of an identifier once.
In your class definition you declare two pointers using the type int (int *pa,*pb), but in your constructor numPair::numPair(int a, int b) you are creating two new pointer declarations (int* pa and int* pb) that only exist within the constructor. From within your class constructor, you can reference its members by name without declaring a type every time, since you already declared them in the class definition. This is why your solution #1 works for you.
Additionally, in your original code, you are leaking the memory allocated on the heap for the values because you do not call delete on those pointers.
This question already has answers here:
When I change a parameter inside a function, does it change for the caller, too?
(4 answers)
Closed 4 years ago.
I know call by pointers in which we pass address of variables.Something like this:
void swap(int *x, int *y)
{
int temp;
temp = *x; /* save the value at address x */
*x = *y; /* put y into x */
*y = temp; /* put x into y */
return;
}
swap(&a, &b);
And also call by reference,in both of these methods the changes made in the function are reflected in actual arguments' variable.
But why are actual parameters passed in this case of call not changed:
#include <iostream>
using namespace std;
void foo(int* c){
c=c+1;
}
int main()
{
int a=5;
int *c=&a;
cout<<&c<<endl; //0x7ffe1a74f3b0
foo(c);
cout<<*c<<endl;//5
cout<<&c<<endl;//0x7ffe1a74f3b0
}
Here c passed to foo() is address of a.So how this is call by value.
Here c should have printed garbage value according to me.Please explain what has happened here.
And also call by reference, in both of these methods the changes made in the function are reflected in actual arguments' variable.
There is an important difference, though: the changes are always made to whatever is referenced/pointed to, never to the reference/pointer itself (modifying a reference is impossible in general).
That is why assigning c a new value inside foo has no effect on c outside foo: the pointer passed to a function is copied.
If you need to modify the pointer, you need to add another level of dereference by passing a pointer reference or a pointer to a pointer.
Following on from comments, the variable c defined in function main is a different variable to the parameter c of function foo. If you want foo to be able to modify main's c, that is modify the address that c's pointer type holds, then you need to pass either a reference or pointer to c to the function instead.
Here is an example that shows the difference between passing c by value (as int *), or by reference (as int ** or int *&). Don't be fooled by the fact that int * is a pointer type, that means that it can receive an int by reference or an int * by value. And since main's c is int * rather than int, main c is being passed by value.
Note the differences in how the functions are called (whether c needs the address operator & in the function call) and the outcome of each function.
#include <iostream>
using namespace std;
void foo_int_ptr(int* c)
{
c=c+1;
}
void foo_int_ptr_ptr(int** c)
{
*c=*c+1;
}
void foo_int_ptr_ref(int*& c)
{
c=c+1;
}
int main()
{
int a=5;
int *c=&a;
cout << "&c=" << &c << ", c=" << c << ", *c=" << (c==&a ? std::to_string(*c) : std::string("INVALID PTR")) << endl;
foo_int_ptr(c);
cout << "&c=" << &c << ", c=" << c << ", *c=" << (c==&a ? std::to_string(*c) : std::string("INVALID PTR")) << endl;
foo_int_ptr_ptr(&c);
cout << "&c=" << &c << ", c=" << c << ", *c=" << (c==&a ? std::to_string(*c) : std::string("INVALID PTR")) << endl;
foo_int_ptr_ref(c);
cout << "&c=" << &c << ", c=" << c << ", *c=" << (c==&a ? std::to_string(*c) : std::string("INVALID PTR")) << endl;
}
Output:
&c=0x7e02d81808b8, c=0x7e02d81808ac, *c=5
&c=0x7e02d81808b8, c=0x7e02d81808ac, *c=5
&c=0x7e02d81808b8, c=0x7e02d81808b0, *c=INVALID PTR
&c=0x7e02d81808b8, c=0x7e02d81808b4, *c=INVALID PTR
there is a mistake in your thinking about this ..
int *c = &a;
this doesn't mean that c "contains" address of a, this means that c is a pointer TO the address of a. Passing a pointer to foo() will not do anything.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
if we create a class like this :
class Sales_data
{
std::string isbn() const {return bookNo;}
std::string bookNo;
};
And we make a object total;
Sales_data total;
total.isbn();
The C++ Primer, fifth edition, says (page 258),"when we call a member function, this is initialized with the address of the object on which the function was invoked "
,it like this:
Sales_data::isbn(&total)
and the book also write,we can get the bookNo like :
std::string isbn()const {return this->bookNo;}
I think the implicit parameter "this" just like a pointer,
but i can't see it type,would anybody help me point what wrong i think and what should i do to understand the implicit parameter 'this' and this parameter works for?
#Jason C
my extra question:
this is a pointer,so it behave like a normal pointer,
#include "iostream"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
int a = 1;
int * b = &a;
cout << "the b is " << b << endl;
cout << "the &a is " << &a << endl;
cout << "the *b is " << *b << endl;
cout << "the &b is" << &b << endl;
return 0;
}
on my computer the output is :
the b is 0110FCEC
the &a is 0110FCEC
the *b is 1
the &b is0110FCE0
then ,What's the use of the type of the pointer.
this is not a parameter, it is a way for an object to refer to itself.
If you use visual studio or any modern IDE you can check that this has the same type as the class of which it is a member of.
There is a good book called "The C++ Object Model" by Stanley B. Lippman which can help understand.
Even if not defined as such in the standard, every implementation I am aware of makes this an implicit parameter to a member function and can be viewed as such.
In C++, you do
object->function () ;
In contrast, in Ada the syntax is
function (object) ;
The object is then an explicit parameter to the member function. The this variable is a product of C++'s member calling syntax. Instead of the programmer having to explicitly declare a parameter identifying the object (as in Ada), C++ does this automatically for you (this).
In most implementations, C++ parameters are bound to offsets to locations on the stack or to registers. This is implemented in the very same way as other parameters (either bound to a stack offset or a register).
this is a pointer to whatever instance of an object the member function is being called on (note that there is no this in static member functions or non-member functions, then).
In your case, it is either a Sales_data * or const Sales_data * depending on the context. Inside isbn(), it is the latter.
This (contrived) example illustrates its value:
class Example {
public:
void function (Example *x);
};
void Example::function (Example *x) {
if (x == this)
cout << "x is this!" << endl;
else
cout << "x is not this." << endl;
}
Now if we do:
Example a;
Example *b = new Example();
a.function(&a); // outputs "x is this!"
b->function(b); // outputs "x is this!"
a.function(b); // outputs "x is not this!"
b->function(&a); // outputs "x is not this!"
Also, since it's a pointer to the "current" instance of the object:
class Example2 {
public:
int k;
void function ();
};
void Example2::function () {
k = 42;
this->k = 42; // does the same thing as above!
}
Suppose I have a class like
class Empty{
Empty(int a){ cout << a; }
}
And then I invoke it using
int main(){
Empty(2);
return 0;
}
Will this cause any memory to be allocated on the stack for the creation of an "Empty" object? Obviously, the arguments need to be pushed onto the stack, but I don't want to incur any extra overhead. Basically I am using the constructor as a static member.
The reason I want to do this is because of templates. The actual code looks like
template <int which>
class FuncName{
template <class T>
FuncName(const T &value){
if(which == 1){
// specific behavior
}else if(which == 2){
// other specific behavior
}
}
};
which allows me to write something like
int main(){
int a = 1;
FuncName<1>(a);
}
so that I get to specialize one template parameter, while not having to specify the type of T. Also, I am hoping the compiler will optimize the other branches away inside the constructor. If anyone knows if this is true or how to check, that would be greatly appreciated. I assumed also that throwing templates into the situation does not change the "empty class" problem from above, is that right?
Quoting Stroustrup:
Why is the size of an empty class not zero?
To ensure that the addresses of two different objects will be different. For the same reason, "new" always returns pointers to distinct objects. Consider:
class Empty { };
void f()
{
Empty a, b;
if (&a == &b) cout << "impossible: report error to compiler supplier";
Empty* p1 = new Empty;
Empty* p2 = new Empty;
if (p1 == p2) cout << "impossible: report error to compiler supplier";
}
There is an interesting rule that says that an empty base class need not be represented by a separate byte:
struct X : Empty {
int a;
// ...
};
void f(X* p)
{
void* p1 = p;
void* p2 = &p->a;
if (p1 == p2) cout << "nice: good optimizer";
}
This optimization is safe and can be most useful. It allows a programmer to use empty classes to represent very simple concepts without overhead. Some current compilers provide this "empty base class optimization".
It might, it might, not, depending on circumstances. If you say:
Empty e;
Empty * ep = & e;
then obviously things have to be allocated.
Try it and see. Many compilers will eliminate such temporary objects when asked to optimise their output.
If the disassembly is too complex, then create two functions with different numbers of such objects and see if there is any difference in the stack locations of objects surrounding them, something like:
void empty1 ( int x )
{
using namespace std;
int a;
Empty e1 ( x );
int b;
cout << endl;
cout << "empty1" << endl;
cout << hex << int ( &x ) << " " << dec << ( &x - &a ) << endl;
cout << hex << int ( &a ) << " " << dec << ( &a - &b ) << endl;
}
and then try running that compared with an empty8 function with eight Empties created. With g++ on x86, if you do take the address of any of the empties you get a location between x and a on the stack, hence including x in the output. You can't assume that the storage for objects will end up in the same order as they are declared in the source code.