In C++ we know that for a pointer of class we use (->) arrow operator to access the members of that class like here:
#include <iostream>
using namespace std;
class myclass{
private:
int a,b;
public:
void setdata(int i,int j){
a=i;
b=j;
}
};
int main() {
myclass *p;
p = new myclass;
p->setdata(5,6);
return 0;
}
Then I create an array of myclass.
p=new myclass[10];
when I go to access myclass members through (->) arrow operator, I get the following error:
base operand of '->' has non-pointer type 'myclass'
but while I access class members through (.) operator, it works. These things make me confused. Why do I have to use the (.) operator for an array of class?
you should read about difference between pointers and reference that might help you understand your problem.
In short, the difference is:
when you declare myclass *p it's a pointer and you can access it's members with ->, because p points to memory location.
But as soon as you call p=new myclass[10]; p starts to point to array and when you call p[n] you get a reference, which members must be accessed using ..
But if you use p->member = smth that would be the same as if you called p[0].member = smth, because number in [] is an offset from p to where search for the next array member, for example (p + 5)->member = smth would be same as p[5].member = smth
Note that for a pointer variable x
myclass *x;
*x means "get the object that x points to"
x->setdata(1, 2) is the same as (*x).setdata(1, 2) and finally
x[n] means "get the n-th object in an array".
So for example x->setdata(1, 2) is the same as x[0].setdata(1, 2).
Because by using [] like p[3] you are already dereferencing the pointer to array + index shift. After that you have to use ".", since p[3] is an object, not a pointer.
After...
MyClass* p = new myclass[10];
...p is a pointer to an array of MyClass objects. The "pointer to an array" thing has to be delt with first. Whenever you have a pointer to an array, p[n] effectively gives you a reference to the nth element in the array, so you effectively have a MyClass&. That's why . is then needed to access MyClass members ala p[n].member, and why the pointer-specific -> notation is erroneous in this case....
Note that p->member (for any member) is still valid and equivalent to p[0].member, so you can only use it for accessing the first element in the array. I strongly recommend you don't use it at all whenever you're in a programmatic context where 'p' is known to be pointer to the array, as it hides the fact that p is an array. Sometimes though you may create another pointer - say q - with the purpose of refering to a single array element - may or may not be [0] - and in those situation's it's fair to use q->member. Variables like q may be used for iteration over the array too. But, sometime you're going to need to delete[] p; - so you won't tend to change p beforehands... you don't want to lose track of the p[0] address or delete[] p; will be Undefined Behaviour (which is allowed to be implementation defined and happens to be on Windows if p still points within the array, but won't be portable).
myclass *ptr;
ptr = new myclass(); // ptr points to a single object
ptr->doSomething(); // calls doSomething on the object _pointed to_
ptr = new myclass[10]; // ptr points to multiple objects
ptr->doSomething(); // calls doSomething on the first object _pointed to_
(ptr+1)->doSomething(); // calls doSomething on the second object _pointed to_
auto val = ptr[2]; // fetches a reference to the second _object_ to val.
val.doSomething(); // calls doSomething on the _object reference_ val.
In other words, when indexing the array to fetch the n'th element, you're not fetching a pointer to the n'th element, you're fetching a reference to the actual object, and the members of that need to be accessed using . syntax.
Perhaps its insightful to consider that, given
myclass obj;
auto p = &obj; // avoid `new` with plain pointers. That combination is
// safer replaced by unique_ptr or std::vector.
the following will all work and are equivalent:
p->setdata(5, 6);
(*p).setdata(5, 6);
p[0].setdata(5, 6);
0[p].setdata(5, 6);
Showing that [] is really a pointer-dereferencing operator, just with the extra functionality that you can add offsets into a plain C-array.
It's generally questionable to use C-arrays in C++ code; the obvious alternative to your example is std::vector:
std::vector<myclass> array(10);
Here, array[n] can be used much like previously p[n], but
You don't get any stupid pointer-ideas, because there are no pointers in the interface
You get proper automatic memory management, i.e. when the array goes out of scope it automatically deletes the objects and its memory
You can get bounds-checks if you want (array.at(n))
You can easily loop over the whole array, with (C++11) for(auto& obj: array){...}.
Related
board *gameBoard = new board(givenX,givenY,givenMineCount);
I know that the above statement declares an object pointer that points to board.
But I'm wondering what the statement below means.
board gameBoard = *new board(givenX,givenY,givenMineCount);
In both statements the "new" keyword returns a pointer to the object you are allocating. The reason the second statement works is because if you put a * before a pointer you dereference that pointer which, in simple terms, gives you the object the pointer is pointing to. But as Mooing Duck said if you don't understand this you should avoid the new keyword all together.
Edit: to answer what it means? it means you allocate a board object then dereference it and save a new copy in your variable gameBoard. Essentially giving you two copies of the Board object.
new board(givenX,givenY,givenMineCount); in a nutshell, performs two things: creates a board object in memory and returns the address where it was created.
In your second statement, gameBoard is a stack variable that holds a board object. As I mentioned before, the new returns an address and by using the * operator, you're basically "interpreting" (the actual technical term is dereferencing) the address as a board. That said, doing this seems to be making a copy and assigning it to boardGame and leave lingering in memory what was created with new.
I'm new to c++, but I think extra details are missing here for beginners like me and like the asker.
Note: This answer contains details for newbies like me.. advanced c++ developers may find this post somewhat confusing!
Lazy? tl;dr at the end
Does always creating and object with *new creates two copies of objects? (one will never ever be deleted)
Lets check this out:
As explained by others, the *new is just a shortcut to new in one statement and then dereference it with the asterisk operator (*)
Consider the following struct that holds a single number:
struct myStruct
{
public:
myStruct() { innerNumber = 0; }
myStruct(uint16_t num) {
innerNumber = num;
}
uint16_t innerNumber;
};
Lets create a SINGLE object, and dereference it MULTIPLE times:
myStruct* obj = new myStruct();
myStruct obj1 = *obj;
myStruct obj2 = *obj;
myStruct obj3 = *obj;
obj1.innerNumber = 1;
obj2.innerNumber = 2;
obj3.innerNumber = 3;
printf("%d-%d-%d\n", obj1.innerNumber, obj2.innerNumber, obj3.innerNumber);
prints: 1-2-3
Pretty cool =] (and dangerous)
So, if we get it correctly, it is ALWAYS a bad idea to use *new as already mentioned here, it will always cause a memory leak!!
lets see it in action:
while (true) {
myStruct& inner = *new myStruct();
delete &inner;
}
That code should:
enter an infinite while loop
allocate a new myStruct object
dereference it (causing it to be copied!)
delete the copy only
Or in shortly: A MEMORY LEAK
Well, I'm running this, and the memory isn't increasing!
*new is GOOD when creating a reference. You can see that I defined
a ref type by the & operator (myStruct& inner)
Another problem that may arise (and is general for references) is that:
// Create a reference
myStruct& inner = *new myStruct();
inner.innerNumber = 0;
// WHAT WILL HAPPEN HERE?
myStruct whatAmI1 = inner;
myStruct whatAmI2 = inner;
whatAmI1.innerNumber = 1;
whatAmI2.innerNumber = 2;
printf("Original: %d Copies: %d-%d\n", inner.innerNumber, whatAmI1.innerNumber, whatAmI2.innerNumber);
prints: Original: 0 Copies: 1-2
dangerous!
TL;DR
*new is bad for creating value types
*new is good for creating reference type
Be careful when assigning a reference type to a value variable, it
makes a copy
I'm working on a project for class and I'm using classes and pointers of type class to call some functions in the class but it's crashing on Code Blocks and Eclipse and I don't know what is going on
Note it crashes when assigning x with y
#include <iostream>
using namespace std;
class a{
private:
int x;
public:
void set_X(int y){
x=y;
}
};
int main()
{
a *Ptr;
Ptr->set_X(5);
}
a *Ptr;
Ptr->set_X(5);
Your Ptr does not point to anything. Trying to invoke a member function on an uninitialised pointer results in undefined behaviour. Crashing is just one of the many more or less random things that can happen.
Luckily, in your example, you do not need a pointer anyway. You can simply write:
a my_a;
my_a.set_X(5);
Pointers often point to dynamically allocated objects. If this is what you want, you must use new and delete accordingly:
a *Ptr = new a;
Ptr->set_X(5);
delete Ptr;
In modern C++, std::unique_ptr is typically a superior alternative because you don't have to manually release the allocated memory, which removes a lot of potential programming errors:
auto Ptr = std::make_unique<a>();
Ptr->set_X(5);
// no delete necessary
Basic rule: creating a pointer (a variable that contains the address of an object, or otherwise is NULL (or nullptr since 2011)) as pointed out by Christian Hackl in comments) does not create a corresponding pointee (an object who's address can be stored in the pointer).
More formally, Ptr is an uninitialised pointer. Even accessing its value gives undefined behaviour (e.g. some_other_pointer = Ptr). For operator -> to work correctly, the pointer must first be initialised so it points at a valid object.
a aobj;
a *Ptr = &aobj;
Ptr->set_X(42); // OK
a *Ptr2 = new a;
Ptr2->set_X(42); // OK
delete Ptr2;
You have just declared a pointer variable of type a* but it doesn't point to a valid memory address. And since you are calling a member function via that pointer which updates a data-member hence you have segfault because this pointer is NULL.
You must initialize pointer with some valid memory address of class a object.
Following can be done,
a* ptr = new a;
ptr->set_X(5);
// ...
delete ptr;
In this case. It would be better that you should use some smart_ptr like std::shared_ptr or std::unique_ptr so that you don't need to worry about releasing resources manually.
Or
a* ptr;
a aobj_;
ptr = &aobj_;
ptr->set_X(5);
I saw in the code next statement:
SomeType someVar[1];
Later someVar is used as a pointer to SomeType. Why would one declare it like this instead of:
SomeType* someVar;
EDIT: As many pointed out, I need to specify the context.
struct SomeStruct
{
size_t count;
SomeType someVar[1];
};
SomeStruct* str = malloc(sizeof(SomeStruct) + sizeof(SomeType) * count);
str->count = count
...
str->someVar is used as an array with count elements of SomeType from this point.
SomeType someVar[1];
someVar is an array of type SomeType with 1 element.
SomeType* someVar;
someVar is a pointer (dangling still, you didn't point it to anything yet) of type SomeType.
And you can use the name of an array on its own as a shorthand for a pointer to the first element of that array.
Will Dean
Because generically speaking they are not the same. The first one defines one element array of SomeType and the other defines pointer to SomeType.
The first allocates memory for that one element, the other does not.
In general: sizeof(SOmeType[1]) != sizeof(SomeType*).
The first can be treated as a pointer to a possibly uninitialized SomeType (initialized if it's a non-POD type). The second is just a dangling pointer.
SomeType someVar[1];
someVar[0]; //valid
*someVar; //valid
vs
SomeType* someVar;
someVar[0]; //invalid
*someVar; //invalid
For the second one to work, you'd need to make it point to something valid, so either an existing object (so then there's no point in having the pointer there), or to a new object allocated with new, in which case there's the downside that you have to call delete yourself.
If you use SomeType*, you will need a new at some point and you will thus have to delete it to avoid leaks.
Using SomeType[] allocates on the stack and the memory management will be handled for you.
SomeType someVar[1]; allocates memory on the stack and it gives you a block/function scoped variable. So it will be automatically destroyed when it is out of the block/function.
SomeType* someVar; is a pointer (to nothing meaningful yet), so it doesn't allocate any for SomeType. However if you have something like this:
SomeType* someVar = malloc(sizeof(SomeType));
of equivalent:
SomeType* someVar = new SomeType(...);
Then that is memory allocation on the heap. So it is not destroyed when out of scope and it needs to be destroyed manually by free or delete.
I'm bit new to C++ and try to work things with Qt and came across this confusing thing:
The concepts on various tutorials state something like:
Class *obj;
*obj - will display the value of object stored at the referenced memory
obj - will be address of memory to which it is pointing
so, I would do something like
*obj=new Class();
but if I want to access a function, I have to do obj->function1();
instead of *obj->function1();
-- not sure why, since with normal objects [ normalObj.function1();] would work, since that's the value directly.
So, for pointer objects why do we use memory reference to access the function,
or is it that in case of normal objects also, its always references
P.S: Can someone guide me to a good tutorial of usage of pointers in C++, so that my queries like these can be directly addressed in it.
The * symbol is used to define a pointer and to dereference a pointer. For example, if I wanted to create a pointer to an int, I could do:
int *ptr;
In this example, the * is being used to declare that this is a pointer to an int. Now, when you are not declaring a pointer and you use the * symbol with an already declared pointer, then you are dereferencing it. As you probably know, a pointer is simply an address. When you dereference a pointer, you are obtaining the value that is being pointed to by that address. For example:
int pointToMe = 5;
int *ptr = &pointToMe;
std::cout << *ptr;
This will print out 5. Also, if you are assigning a pointer to a new address and it's not in the declaration, you do not use the * symbol. So:
int pointToMe = 5;
int *ptr;
ptr = &pointToMe;
is how you would do it. You can also deference the pointer to assign a new value to the value being pointed to by the address. Such as:
int pointToMe = 5;
int *ptr = &pointToMe;
std::cout << *ptr; // Prints out 5
*ptr = 27;
std::cout << *ptr; // Prints out 27
Now, -> acts like the deference symbol. It will dereference the pointer and then use the member functions and variables as if you had used . with a non-pointer object. Even with an object that is not a pointer you can use the -> by first getting the address:
CObj object;
(&object)->MemberFunction();
That's just a brief overview of pointers, hope it helps.
You can use the "normal" . to access the objects members, but you have to dereference the pointer first.
Due to operator precedence, this will look like (*obj).member. For those who think this is too much to write, obj->member is a shorter alternative.
If you have an object c of type Class, *c.ptr means dereferencing a pointer ptr that is a member of Class. That is one reason for (*obj).member, which means something else.
Actually, you're wrong. You do:
obj=new Class();
or
Class *obj = new Class;
which are completely different.
Class *obj;
*obj = new Class;
wouldn't compile.
obj is of type Class*, so that's what you can assign to it (and what new Class returns).
More precisely u can do like this
Class obj;
Class* obj_ptr;
obj_ptr = &obj;
// Now onwards you can use the pointer to access data members and function
obj_ptr->a = 10; // Like this
Im playing with my smart pointer class and I want to implement ++ and -- operators with the following behavior: If pointer points to single variable or if it points to array and ++(--) moves pointer out of array bounds an exception should be thrown when trying to ++(--).
Something like that:
class A;
SmartPtr<A> s(new A[3]);
SmartPtr<A> s1(new A());
++s;//ok
--s;//ok
--s;//exception OutOfBounds thrown
++s1;//exception OutOfBounds thrown
--s1;//exception OutOfBounds thrown
I tried to use typeid. But it returns A type anyway.
A* arr=new A[3];
typeid(arr).name();//type is P1A
typeid(--arr).name();//type is P1A
typeid(arr+7).name();//type is P1A
So is there any way to determine does pointer point to "my" type of object after ++(--)?
new A[3] returns an A*, just like new A does. So you can't distinguish them.
If you want your class to do bounds checking, then you will need to explicitly tell it how many items are in the array.
No, if you want to implement this kind of behaviour, you must store somewhere the size of the allocated array.
You can only do this kind of bounds checking if you use a utility function, rather than array new directly, e.g.:
template <class Type, std::size_t size>
SmartPtr<Type> MakeArrayPtr()
{
return SmartPtr<Type>(new Type[size], size);
}
If the smart pointer deletes the object, remember to have it use delete[] in the case of arrays.
stop using raw pointers/raw arrays and start using a vector. Then you can get the size of the vector and simply store the position of the element in your smart pointer class.