c++ assign to pointer a pointer to constant - c++

I have the following code:
class B{
/*
...
*/
};
class A{
B** elements;
public:
A operator+=(const B& b){
// this->elements[0] = &b;
}
A(int number){
this->elements = new B*[number];
}
/*
...
*/
};
int main(){
A a(10);
return 0;
}
What I want is that the += operator should add the B object(operator's right side) to the A object's elements member.
So let's say I modify main to :
int main{
A a(10);
B b();
a += b;
}
After this a.elements[0] should be the b object.
I commented a line which is not working,but shows what I want.Uncommenting it gives the following error: invalid conversion from const B* to B*
The real code is much longer of course, it's enough if you show me how to make the += operator always assign the B object to A.elements[0], then I can edit my code as neccessary.
Thanks

Focusing your issue, a B* is not a B const*: on the first you are allowed to call methods which are not const, while this is not true for the latter.
And the compiler is complaining about this: you declare an array of pointers to modifiable Bs but then you try to store a pointer to an unmodifiable B inside it. So if you merely want to fix this problem you can decide for example to store unmodifiable Bs:
B const** elements;
public:
A& operator+=(const B& b) {
this->elements[0] = &b;
return *this;
}
A(int number) {
this->elements = new B const*[number];
}
But there are serious issues in your code:
you are taking the address of a const B& but where is this B coming from? It could have automatic storage and become an invalid pointer somewhere in the future
there is no way to know who is owning the pointer to B objects so who is responsible of releasing it.
It's C++, you have std::unique_ptr, std::shared_ptr, std::vector, just trying to do things as you would do them in C without even attempting to make them safe and secure doesn't make any sense.

You have some serious issues with your design.
A operator+=(const B& b){
// this->elements[0] = &b;
The idea here is to insert b into your collection, but your collection is little more than a pointer to some (unknown length) amount of raw memory. You do not have a way to know if elements[x] exists in order to store &b. For that matter, you don't know if elements exists at all. You will need more bookkeeping to store lengths.
But worse, you pass a reference to a const B and take its address, storing that pointer in your collection. What if the argument is a reference bound to a temporary? (Rvalues can bind to const lvalue references). In that case, the moment you've finished inserting the pointer into your collection the object it points to is destroyed.
That is assuming you work around your const-incorrectness, as you take a reference to a const b, take its address, and hope that it points to a non-const B. It doesn't. Casting it away can result in undefined behavior if b really points to an actually const object (and the non-const interface of b is used through your pointer.)
Your grow function leaks memory and loses the old elements. Yes, it's pseudocode but too far from anything real to base ideas on.
There is a lot of really dangerous ideas in just a few lines. Here are suggestions:
do not store raw pointers
even more strongly, do not store pointers obtained from reference arguments
make lifetime management easy; use smart pointers to show who owns the memory of passed-in objects
maintain const correctness. If you take (smart) pointers to const objects, store them as (smart) pointers to const objects.
when you resize allocations allocations, worry about what happens to the old objects and memory. Containers help reduce this effort.
use container classes instead of managing raw memory yourself and many of your problems vanish (but not the lifetime management issue of the arguments.)

Related

Why would I want to use a smart pointer in this situation?

I never used any kind of smart pointer, but I keep reading about them almost everywhere when the topic is pointers. I do understand that there are situations where smart pointers are much nicer to work with than raw pointers, because to some extend they manage ownership of the pointer. However, I still do not know, where is the line between "I do not needing smart pointers for that" and "this is a case for smart pointers".
Lets say, I have the following situation:
class A {
public:
double get1(){return 1;}
double get2(){return 2;}
};
class SomeUtilityClass {
public:
SomeUtilityClass(A* a) : a(a) {}
double getResult(){return a->get1() + a->get2();}
void setA(A* a){a = a;}
private:
A* a;
};
int main(int argc, char** argv) {
A a;
SomeUtilityClass u(&a);
std::cout << u.getResult() << std::endl;
A a2;
u.setA(&a2);
std::cout << u.getResult() << std::endl;
return 0;
}
This is of course an oversimplified example. What I mean is that SomeUtilityClass is not supposed to "own" an instance of A (because it is just a utility class), thus it just holds a pointer.
Concerning the pointer, the only thing that I am aware of that could go wrong is:
SomeUtilityClass can be instantiated with a null pointer
The object pointed to may be deleted/go out of scope, without the SomeUtilityClass noticing it
How could a smart pointer help to avoid this problem? What other benefits I would get by using a smart pointer in this case?
PS: I know that there are several question on smart pointers (e.g. this one). However, I would appreciate, if you could tell me about the impact on this particular example.
This depends on how the parameter is created and stored. If you don't own the memory and it could be either statically or dynamically allocated, a raw pointer is a perfectly reasonable solution -- especially if you need to support swapping of the data as in your example. Another option would be to use std::reference_wrapper, which would get rid of your nullptr issue whilst keeping the same semantics.
If you are holding a pointer to some shared resource (i.e. stored in a std::shared_ptr somewhere) and want to be able to check if it has been deleted or not, you could hold a std::weak_ptr.
For the purposes of this answer I'm redefining setA as:
void setA(A* new_a){a = new_a;}
Consider:
// Using your SomeUtilityClass
int main() {
A a;
SomeUtilityClass u(&a);
// We define a new scope, just because:
{
A b;
u.setA(&b);
}
std::cout << u.getResult() << '\n';
return 0;
}
After the scope is finished, SomeUtilityClass has a dangling pointer and getResult() invokes Undefined Behaviour. Note that this can't be solved with a reference: You would still get a dangling one.
Now consider the version using a smart pointer:
class SomeUtilityClass {
public:
SomeUtilityClass(std::shared_ptr<A>& a) : a{a} {}
double getResult(){return a->get1() + a->get2();}
void setA(std::shared_ptr<A>& new_a){a = new_a;}
private:
std::shared_ptr<A> a;
};
int main() {
std::shared_ptr<A> a{new A};
SomeUtilityClass u{a};
// We define a new scope, just because:
{
std::shared_ptr<A> b{new A};
u.setA(b);
}
std::cout << u.getResult() << '\n';
return 0;
}
Because you have shared ownership, there's no way to get a dangling pointer. The memory pointed to by b will be deleted as usual, but only after u is destroyed(or its pointer is changed).
IMHO, in most cases you should be using smart pointers (Even when at first it doesn't seem to make much sense). It makes maintenance much easier. Use raw pointers only in specific code that actually needs them, and encapsulate/isolate this code as much as possible.
If SomeUtilityClass does not own the member variable a, then a smart pointer does not make sense.
You might consider a reference member, which would remove the problems of a null pointer.
The default way of expressing not-owning pointer in C++ is weak_ptr. To use weak_ptr you need to use shared_ptr for ownership, so in your example you would use
shared_ptr<A> owner(...)
instead of
A a
Then as the private pointer member of your SomeUtilityClass you use weak pointer:
weak_ptr<A> w;
and initialise it with shared_ptr:
SomeUtilityClass(shared_ptr<A> o) : w(o) {}
however, you cannot use weak_ptr directly, since the shared_ptr could go out of scope and your weak pointer can no longer point to anything. Before use you need to lock it:
shared_ptr<A> locked = w.lock();
The locked pointer will be empty if the owning pointer no longer manages an object, since e.g. it went out of scope. If it is not empty, you may use it and then it will go out of scope automatically releasing the lock the object.
Both shared_ptr and weak_ptr are available in standard library in C++11, and in Boost for older compilers.
There are different types of smart pointers. In your case, it is clear that a smart pointer is not really needed, but it may still provide some benefits.
SomeUtilityClass can be instantiated with a null pointer
This one is probably best solved with a check in the constructor, throwing an exception or indicating an error in some other way in the case when you get a NULL pointer as the argument. I can hardly imagine how a smart pointer would help, unless you use a specific smart pointer class that doesn't accept NULLs, so it does the check for you already.
The object pointed to may be deleted/go out of scope, without the
SomeUtilityClass noticing it
This one can actually be resolved with a special type of smart pointers, but then it is needed that the object being pointed to somehow supports notification of destruction. One such example is the QPointer class in the Qt library, which can only point to QObject instances, which notify it when deleted, so the smart pointer automatically becomes NULL when the object is deleted. There are some problems with this approach, though:
You need to check for NULLs every time you access the object through the smart pointer.
If a smart pointer points to an instance of a class, say MyClass, extending the class performing the deletion notification (QObject in the Qt case), you get strange results: it's the destructor of QObject that notifies the smart pointer, so it is possible that you access it when the MyClass destructor already began its dirty work, so the object is partially destructed, but the pointer is not NULL yet because the destruction is still in progress.

Why memory is not allocated to class when we create pointer type object?

I am little bit curious about that why memory is not allocated to a class or structure when we create pointer type object ?
For example :-
class A
{
public:
void show()
{
cout<<" show function "<<endl;
}
};
int main()
{
A *a;
a->show();
return 0;
};
Because pointers and memory allocation are a priori completely unrelated. In fact, in modern C++ it’s downright bad to use pointers to point to manually allocated memory directly.
In most cases, pointers point to existing objects – that’s their purpose: to provide indirection. To reiterate: this is completely unrelated to memory allocation.
If you want to directly have an object you don’t need a pointer: just declare the object as-is (= by value):
A a;
a.show();
This code:
A *a;
a->show();
just declares a pointer of type A*. Pointer alone is nothing but a variable that holds an address of some memory in it, i.e. it just points somewhere, nothing else. Pointer of type A* means that it points to memory, where an instance of type A is expected to be found.
a->show(); then just relies on this "expectation", but in fact it just uses uninitialized pointer, which results in undefined behavior.
This could be either solved by dynamically creating an instance of A:
A *a = new A();
a->show();
(which however gives you unpleasant responsibility for cleaning up this memory by calling delete a;) or even better: using an object with automatic storage duration instead:
A a;
a.show();
In the second case, an instance of type A is created automatically and its lifetime is tied to the scope, in which it has been created. Once the execution leaves this scope, a is destructed and memory is freed. All of that is taken care of, without you worrying about it at all.
Allocating a pointer does not equate to allocating an object. You need to use new and instantiate an object on the heap, or create the object on the stack:
A* a = new A();
// Or
A a;
A* aPntr = &a;
Pointer is not an object, it’s just a link that points somewhere. The reason to use them is that you can dynamically change what they’re pointing to.
A a;
A b;
A *pA;
{
bool condition;
// set condition here according to user input, a file or anything else...
if(condition)
pA = &a;
else
pA = &b;
}
Now I don’t have to take care about condition, it even doesn’t have to exist anymore and still I can profit from the choice made above.
pA->show();
Or I can use pointer to iterate over an array:
A array[10];
for(A* pA = array; pA < array+10; pA++)
{
pA->show();
}
(Note I used the original declaration of class A in both examples altough more meaningful it would be if each object of class A contained its specific information.)
There may not be one single reason for A *a; not to allocate an instance of A. It would be at odds with how C++ is designed. I would be somewhat surprised if Stroustrup considered it for long enough to identify a definitive reason not to do it.
A few different ways to look at it:
You didn't ask for an object of type A, so you don't get one. That's how C and C++ work.
A pointer object is an object that holds an address. You may as well ask why stationary manufacturers don't build a house when they manufacture an envelope, as ask why C++ doesn't allocate an object to be pointed at when you define a pointer.
There are many ways to allocate memory. Supposing that memory was going to be allocated, which one would you like? You could argue that in C++ new would be a sensible default for class types, but then it would probably be quite confusing either if char *c; called new char (because the behavior would be different from C) or if char *c; didn't allocate memory at all (because the behavior would be different from char *A;.
How and when would the memory be freed? If it's allocated with new then someone is going to have to call delete. It's much easier to keep things straight if each delete corresponds to a new, rather than each delete corresponding either to new or to defining a pointer with implicit memory allocation.
A pointer can be the location of an object, but it isn't always (sometimes it's null, sometimes it's off-the-end of an array). The object can be dynamically allocated but doesn't have to be. It would be very unhelpful of the language to make a pointer point to an object in cases where you don't need it. Therefore the language gives you the option not to allocate memory when defining a pointer. If you don't want that, then you should initialize the pointer with the result of a call to the memory-allocation mechanism of your choice.
You just create a pointer *a, but not allocate memory for it.
you should use A *a = new A();

C++: Difference between pointer syntaxes

Alright so I've been getting deeply into C++ as of late and I'm getting everything down. Pointers are finally starting to make sense as far as when I should use them, how to implement them correctly, etc.
However, there was one little question about the fundamental use of pointers that I still had that needed answered. I'll jump right to the code:
With the following class A and function foo(A* bar)...
class A
{}
void foo(A* bar)
{}
... what's the difference between the following calls to foo?
A* a;
A b;
foo(a);
foo(&b);
They both compile fine, and as far as I can remember I haven't had any issues with them.
I think that A b; is instantiated right there, whereas A* a; needs to be created with new (since it hasn't actually created the object, it's just held a 4-byte long reference to a potential A object).
I could, if I am thinking about this correctly, do a = b; (EDIT make that a = &b) and then successfully pass a to foo. But, if I don't do a = &b and foo tries to read the (non-existent) object pointed to by a, it will causes runtime errors.
Also, if the above is correct, then it's assumed I can successfully call foo(&b); just fine.
Am I correct?
Thanks!
Yes, Your understanding is correct.
foo(&b);
passes address of an already existing object of type A as an parameter to function foo().
foo(a);
passes a pointer to the type A as function parameter. To be able to do anything meaningful it must point to a valid A object.It can be done in two ways:
Allocating object on stack:
Create an object of the type A on stack(local storage) & make the pointer a point to this object:
A* a;
A b;
a = &b;
Dynamic Memory allocation:
A *a = new A;
Though, Once you do a dynamic memory allocation you will have to remember to free the alloated memory explicitly after use, or you will have a memory leak:
delete a;
Note that it is always better to avoid dynamic allocations as far as possible, and if you must do so, use Smart pointers instead of raw pointers.
You can't do a = b.
It would have to be a = &b, to set a to the address of b.
You are also correct about the memory management: b is allocated on the stack, while a allocates space only for a pointer and leaves creating the actual object to you.
foo(&b) will work file, where the behavior of foo(a) would be undefined before you initialize *a (such as via a = new A()).
In C++, pointers are first-class objects. A pointer isn't just an invisible reference that needs an associated object to have an identity. That's how Java/C# references work (or most other languages, really), but a pointer is an object in itself.
So A* a declares a pointer. It doesn't point to anything, and it doesn't have to point to anything. And if/when it points to something, it doesn't need to own that something.
So you don't need to do a = new A(). You can do a = &b as well (to have a contain the address of the object b. Or it can point to any other object of type A as well. A pointer is just an object that stores an address. It's key to your understanding that you throw away the notion that it "has an object" which "needs to be created".
It is an object, which contains an address (or it contains the special value null), and if it contains an address, there may or may not be an object of type A at that address.
You are mostly correct. You should not assume that pointers are 4 bytes (for example, it might be 8 on amd64 systems). Also, your assignment should be a = &b; (note the addition of the address operator). Other than that, it sounds pretty reasonable.

C++: making shallow copy of an object a) syntax b) do i need to delete it

I have a class MyClassA. In its constructur, I am passing the pointer to instance of class B. I have some very basic questions related to this.
(1) First thing , is the following code correct? ( the code that makes a shallow copy and the code in methodA())
MyClassA::MyClassA(B *b){
this.b = b;
}
void MyClassA::methodA(){
int i;
i = b.getFooValue();
// Should I rather be using the arrow operator here??
// i = b->getFooValue()
}
(2) I am guessing I don't need to worry about deleting memory for MyClassA.b in the destructor ~MyClassA() as it is not allocated. Am I right?
thanks
Update: Thank you all for your answers! MyclassA is only interested in accessing the methods of class B. It is not taking ownership of B.
You need the arrow operator since b is a pointer.
Yes, unless the user of MyClassA expects to take the ownership of b. (You can't even be sure if b is a stack variable where delete-ing it will may the code crash.)
Why don't you use a smart pointer, or even simpler, a reference?
First thing , is the following code
correct? ( the code that makes a
shallow copy and the code in
methodA())
The answer depends upon who owns the responsibility of the B object's memory. If MyClassA is supposed just to store the pointer of A without holding the responsibility to delete it then it is fine. Otherwise, you need to do the deep copy.
I am guessing I don't need to worry
about deleting memory for MyClassA.b
in the destructor ~MyClassA() as it is
not allocated. Am I right?
Again depends on how memory for B is allocated. Is it allocated on stack or heap? If from stack then you need not explicitly free it in destructor of MyClassA, otherwise you need to to delete it.
1) . It depends on the life time of the pointer to B.
Make sure the when you call b->getFooValue(); b should be a valid pointer.
I will suggest use of initilization list and if you are only reading the value of the B object though it pointer then make it pointer to constant data.
MyClassA::MyClassA(const B *bObj) : b(bObj)
{}
2). As long as B is on the stack on need to delete it and if it is allocated to heap then it must be deleted by it the owner else you will have memory leak.
You can use smart pointer to get rid of the problem.
MyClassA::MyClassA(B *b){
this.b = b;
}
should be:
MyClassA::MyClassA(B *b){
this->b = b;
}
because this is treated as a pointer.
1)
this.b = b;
Here you pass a pointer to an instance of B. As Mac notes, this should be:
this->b = b;
b.getFooValue();
This should be b->getFooValue(), because MyClassA::b is a pointer to B.
2) This depends of how you define what MyClassA::b is. If you specify (in code comments) that MyClassA takes over ownership over the B instance passed in MyClassA's constructor, then you'll need to delete b in MyClassA's destructor. If you specify that it only keeps a reference to b, without taking over the ownership, then you don't have to.
PS. Regrettably, in your example there is no way to make ownership explicit other than in code documentation.

Lifetime management of encapsulated objects

What is the best approach to encapsulate objects and manage their lifetime? Example: I have a class A, that contains an object of type B and is solely responsible for it.
Solution 1, clone b object to ensure that only A is able to clean it up.
class A
{
B *b;
public:
A(B &b)
{
this->b = b.clone();
}
~A()
{
delete b; // safe
}
};
Solution 2, directly use the passed object, we risk a potential double free here.
class A
{
B *b;
public:
A(B *b)
{
this->b = b;
}
~A()
{
delete b; // unsafe
}
};
In my actual case, solution #2 would fit best. However I wonder if this is considered bad code because someone might not know about the behavior of A, even if it's documented. I can think of these scenarios:
B *myB = new B();
A *myA = new A(myB);
delete myB; // myA contains a wild pointer now
Or,
B *myB = new B();
A *firstA = new A(myB);
A *secondA = new A(myB); // bug! double assignment
delete firstA; // deletes myB, secondA contains a wild pointer now
delete secondA; // deletes myB again, double free
Can I just ignore these issues if I properly document the behavior of A? Is it enough to declare the responsibility and leave it up to the others to read the docs? How is this managed in your codebase?
I never delete anything myself unless I really have to. That leads to errors.
Smart pointers are your friend. std::auto_ptr<> is your friend when one object owns another and is responsible for deleting it when going out of scope. boost::shared_ptr<> (or, now, std::tr1::shared_ptr<>) is your friend when there's potentially more than one object attached to another object, and you want the object deleted when there's no more references to it.
So, either use your solution 1 with auto_ptr, or your solution 2 with shared_ptr.
You should define your object so that the ownership semantics are, as much as possible, defined by the interface. As David Thornley pointed out, std::auto_ptr is the smart pointer of choice to indicate transfer of ownership. Define your class like so:
class A
{
std::auto_ptr<B> b;
public:
A(std::auto_ptr<B> b)
{
this->b = b;
}
// Don't need to define this for this scenario
//~A()
//{
// delete b; // safe
//}
};
Since the contract of std::auto_ptr is that assignment = transfer of ownership, your constructor now states implicitly that an A object has ownership of the pointer to B it's passed. In fact, if a client tries to do something with a std::auto_ptr<B> that they used to construct an A after the construction, the operation will fail, as the pointer they hold will be invalid.
If you are writing code that someone else will be using later, these issues must be addressed. In this case I would go for simple reference counting (maybe with smart pointers). Consider the following example:
When an instance of the encapsulating class is assigned an object B, it calls a method to increase object's B reference counter. When the encapsulating class is destroyed, it doesn't delete B, but instead calls a method do decrease reference count. When the counter reaches zero, object B is destroyed (or destroys itself for that matter). This way multiple instances of encapsulating class can work with a single instance of object B.
More on the subject: Reference Counting.
If your object is solely responsible for the passed object then deleting it should be safe. If it is not safe than the assertion that you are solely responsible is false. So which is it? If you're interface is documented that you WILL delete the inbound object, then it is the caller responsibility to make sure you receive an object that must be deleted by you.
If you're cloning A, and both A1 and A2 retain references to B, then B's lifetime is not being controlled entirely by A. It's being shared among the various A. Cloning B ensures a one-to-one relationship between As and Bs, which will be easy to ensure lifetime consistency.
If cloning B is not an option, then you need to discard the concept that A is responsible for B's lifetime. Either another object will need to manage the various B, or you'll need to implement a method like reference counting.
For reference, when I think of the term 'Clone', it implies a deep copy, which would clone B as well. I'd expect the two As to be completely detached from each other after a clone.
I don't clone things unnecessarily or "just to be safe".
Instead I know whose responsibility it is to delete something: either via documentation, or by smart pointers ... for example, if I have a create function which instantiates something and returns a pointer to it and doesn't delete it, so that it's unclear where and by whome that thing is ever supposed to be deleted, then instead of create's returning a naked pointer I might define create's return type as returning the pointer contained within some kind of smart pointer.