c++ method argument class reference - c++

I'm sorry to ask such a newbie question.
Here is my problem :
MyClass* c = new MyClass("test");
method(c);//error cannot convert MyClass* to MyClass
the definition :
method(MyClass c);
should I also define ?
method(MyClass* c);
I don't want to duplicate the code, what is the proper way ?

You're clearly a Java programmer! First of all, you will need to do:
MyClass* c = new MyClass("test");
Note that c is a "pointer to MyClass" - this is necessary because the new expression gives you a pointer to the dynamically allocated object.
Now, to pass this to a function that takes a MyClass argument, you will need to dereference the pointer. That is, you will do:
method(*c);
Note that because the function takes a MyClass by value (not a reference), the object will be copied into your function. The MyClass object inside method will be a copy of the object you allocated earlier. The type of the argument depends on exactly what you want your function to do and convey. If instead you want a reference to the object, so that modifying the object inside the function will modify the c object outside the function, you need your function to take a MyClass& argument - a reference to MyClass.
If you were to have the argument be of type MyClass*, then you could simply do:
method(c);
This will give you similar semantics to passing a reference, because the pointer c will be copied into the function but the object that pointer refers to will still be the dynamically allocated MyClass object. That is, if inside the function you modify *d, the object pointed to by c is also modified.
Passing a raw pointer like this is usually not a very good approach. The function will have to explicitly check that the pointer is not null, otherwise your program may crash under certain conditions. If you want pass-by-reference semantics, use reference types - it's what they're for.
However, you're better off not dynamically allocating your MyClass object in the first place. I guess you're only using new because you did it a lot in Java. In C++, the new expression is used to dynamically allocate an object. More often than not, you do not want to dynamically allocate an object. It is perfectly fine to create it with automatic storage duration, which you would do like so:
MyClass c("test");
method(c);
It is considered very good practise in C++ to avoid pointers and dynamic allocation unless you have a good reason. It will only lead you to more complicated code with more room for errors and bugs. In fact, the code you've given already has a problem because you didn't delete c;. When you do as I have just suggested, you don't need to explicitly delete anything, because the object will be destroyed when it goes out of scope.

MyClass *c = new MyClass("test");
method(*c);
it works if you defined a method like method(MyClass c)
But if you define you method like method(MyClass *c);
then it should be
MyClass *c = new MyClass("test");
method(c);
The two alternatives have consequences depending on what you want to do with the object you have created.

Related

Using new to create new storage and returning a reference

I am reading the book c++ primer plus and I feel confused about the reference variables and pointers.
Here are two pieces of code extracted from page 400 of the book.
const free_throws & clone(free_throws & ft)
{
free_throws * pt;
*pt = ft;
return *pt;
}
const free_throws & clone2(free_throws & ft)
{
free_throws newguy;
newguy = ft;
return newguy;
}
The book said that the first one is okay but the second one is invalid. Is it true that a pointer variable will still exist after the function terminates even if it is declared within the function?
Another question is why can we omit the new keyword in the first piece of code? If we can just create a nameless structure and assign something to it, why do we need the new keyword?
Thank you in advance.
For the first one, the book provided a few lines of explanation.
The first statement creates a nameless free_throws structure. The pointer pt points to the structure, so *pt is the structure. The code appears to return the structure, but the function declaration indicates that the function really returns a reference to this structure.
Both functions have problems. The first function's problem is that pt does not point at a valid free_throws object, so doing *pt = ft; gives you undefined behaviour (you are assigning to a non-existent object). The second function's problem is that you're returning a reference to a local variable which will be destroyed when the function returns (a dangling reference).
Is it true that a pointer variable will still exist after the function terminates even if it is declared within the function?
No. A locally declared pointer is just like any other locally declared object - it will be automatically destroyed at the end of the function. The object that it points at may have a different lifetime, however.
Another question is why can we omit the new keyword in the first piece of code? If we can just create a nameless structure and assign something to it, why do we need the new keyword?
You can't.
If you want to create an object that lasts beyond the scope of a function, you can use a new-expression (like new free_throws()). This creates an object with dynamic lifetime, which you must later destroy manually with delete.
To demonstrate, your first function would be okay (at least not invoke undefined behaviour) if you dynamically allocated a free_throws object for pt to point to:
const free_throws & clone(free_throws & ft)
{
free_throws * pt = new free_throws();
*pt = ft;
return *pt;
}
However, it's still a really bad function because it really doesn't make it clear that the object being returned needs to be destroyed manually. Good C++ code will manage the ownership of dynamically allocated objects using smart pointers. At the very least, you should use raw pointers, simply because C++ developers know to look out for them, and document that your function dynamically allocates the objects it returns.
However, it is typically much better to write a function without any dynamic allocation at all. If you were to do that with this clone function though, you would just discover how pointless it is. Might as well just use the copy constructor instead of writing an extra function.

Return by reference in C++ - Reference assignment vs value assignment

Suppose I have:
class SomeObject {
};
SomeObject& f() {
SomeObject *s = new SomeObject();
return *s;
}
// Variant 1
int main() {
SomeObject& s = f();
// Do something with s
}
// Variant 2
int main() {
SomeObject s = f();
// Do something with s
}
Is there any difference between the first variant and the second? any cases I would use one over the other?
Edit: One more question, what does s contain in both cases?
First, you never want to return a reference to an object which
was dynamically allocated in the function. This is a memory
leak waiting to happen.
Beyond that, it depends on the semantics of the object, and what
you are doing. Using the reference (variant 1) allows
modification of the object it refers to, so that some other
function will see the modified value. Declaring a value
(variant 2) means that you have your own local copy, and any
modifications, etc. will be to it, and not to the object
referred to in the function return.
Typically, if a function returns a reference to a non-const,
it's because it expects the value to be modified; a typical
example would be something like std::vector<>::operator[],
where an expression like:
v[i] = 42;
is expected to modify the element in the vector. If this is
not the case, then the function should return a value, not
a reference (and you should almost never use such a function to
initialize a local reference). And of course, this only makes
sense if you return a reference to something that is accessible
elsewhere; either a global variable or (far more likely) data
owned by the class of which the function is a member.
In the first variant you attach a reference directly to a dynamically allocated object. This is a rather unorthodox way to own dynamic memory (a pointer would be better suited for that purpose), but still it gives you the opportunity to properly deallocate that object. I.e. at the end of your first main you can do
delete &s;
In the second variant you lose the reference, i.e. you lose the only link to that dynamically allocated object. The object becomes a memory leak.
Again, owning a dynamically allocated object through a reference does not strike me as a good practice. It is usually better to use a pointer or a smart pointer for that purpose. For that reason, both of your variants are flawed, even though the first one is formally redeemable.
Variant 1 will copy the address of the object and will be fast
Variant 2 will copy the whole object and will be slow (as already pointed out in Variant2 you cant delete the object which you created by calling new)
for the edit: Both f contain the same Object
None of the two options you asked about is very good. In this particular case you should use shared_ptr or unique_ptr, or auto_ptr if you use older C++ compilers, and change the function so it returns pointer, not reference. Another good option is returning the object by value, especially if the object is small and cheap to construct.
Modification to return the object by value:
SomeObject f() { return SomeObject(); }
SomeObject s(f());
Simple, clean, safe - no memory leaking here.
Using unique_ptr:
SomeObject* f() { return new SomeObject(); }
unique_ptr<SomeObject> s(f());
One of the advantages of using a unique_ptr or shared_ptr here is that you can change your function f at some point to return objects of a class derived from SomeObject and none of your client code will need to be changed - just make sure the base class (SomeObject) has a virtual constructor.
Why the options you were considering are not very good:
Variant 1:
SomeObject& s = f();
How are you going to destroy the object? You will need address of the object to call it's destructor anyway, so at some point you would need to dereference the object that s refers to (&s)
Variant 2. You have a leak here and not a chance to call destructor of the object returned from your function.

C++: Reference to dynamic memory

All considerations about when to use which aside, I am still unsure about pointer vs reference semantics.
Right now, I am under the impression that references are essentially pointers that must be initialized when they are declared, and then from that point on cannot point to anything else. In other words, they are a like a Type* const (not Type const*), or, they cannot be reseated. It essentially becomes a "new name" for that object. Now I heard that references do not actually need to be implemented by the compiler using pointers, but I am under the impression that you can still think of them this way, in regards to what their visible behavior will be.
But why can't you do something like this:
int& foo = new int;
I want to create a reference to dynamic memory. This does not compile. I get the error
error: invalid initialization of non-const reference of type 'int&' from a temporary of type 'int*'
That makes sense to me. It seems the new operator returns a pointer of given type to the address of memory that the OS? dynamically allocated for me.
So how do I create a "reference" to dynamic memory?
Edit: Links to resources that precisely explain the difference between references and pointers in C++ would be appreciated.
new returns a pointer to the allocated memory, So you need to capture the return value in a pointer.
You can create a reference to a pointer after allocation is done.
int *ptr = new int;
int* &ref = ptr;
then delete it after use as:
delete ref;
or more simply,
int &ref = *(new int);
delete it after use as:
delete &ref;
References are syntactic sugar. They allow one to access an object with the dot operator rather than the arrow.
Your choice of whether to use a pointer or a reference is semantic. When you pass an object by reference to a method, or return a reference from a method, you are saying: "This is my object and you may use it, but I own it (and it may be on the stack or the heap.)" It follows that the other answers here which suggest syntax like delete &foo; might technically work, but smell bad; If you have a reference to an object then you shouldn't be deleting it. You don't own it and, most importantly, as you can't reset the reference you end up with a reference to deallocated memory, which is a bad thing.
Now, if you have allocated an object on the heap (called 'new' to create it) then you do own it, and are responsible for cleaning it up later, so you need to hold a pointer to it. Why? So you can safely delete it later and null-out the pointer.
It follows that the difference between a pointer and a reference, other than the mechanical difference of using dot rather than arrow, is that by passing by reference to a method you indicate something about how an object should be used. To initialise a reference directly by calling new is nonsense, even if possible.
You can get a reference like this:
int& foo = *(new int);
In general, to get from T* to T& you use * to "dereference" the pointer.
However this is not a very good idea in the first place. You usually use pointers to store addresses of heap-allocated objects.

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.

Deleting a pointer to const (T const*)

I have a basic question regarding the const pointers. I am not allowed to call any non-const member functions using a const pointer. However, I am allowed to do this on a const pointer:
delete p;
This will call the destructor of the class which in essence is a non-const 'method'. Why is this allowed? Is it just to support this:
delete this;
Or is there some other reason?
It's to support:
// dynamically create object that cannot be changed
const Foo * f = new Foo;
// use const member functions here
// delete it
delete f;
But note that the problem is not limited to dynamically created objects:
{
const Foo f;
// use it
} // destructor called here
If destructors could not be called on const objects we could not use const objects at all.
Put it this way - if it weren't allowed there would be no way to delete const objects without using const_cast.
Semantically, const is an indication that an object should be immutable. That does not imply, however, that the object should not be deleted.
Constructors and Destructors should not be viewed as 'methods'. They are special constructs to initialise and tear down an object of a class.
'const pointer' is to indicate that the state of the object would not be changed when operations are performed on it while it is alive.
I am not allowed to call any non-const member functions using a const pointer.
Yes you are.
class Foo
{
public:
void aNonConstMemberFunction();
};
Foo* const aConstPointer = new Foo;
aConstPointer->aNonConstMemberFunction(); // legal
const Foo* aPointerToConst = new Foo;
aPointerToConst->aNonConstMemberFunction(); // illegal
You have confused a const pointer to a non-const object, with a non-const pointer to a const object.
Having said that,
delete aConstPointer; // legal
delete aPointerToConst; // legal
it's legal to delete either, for the reasons already stated by the other answers here.
Another way to look at it: the precise meaning of a const pointer is that you will not be able to make changes to the pointed-to object that would be visible via that or any other pointer or reference to the same object. But when an object destructs, all other pointers to the address previously occupied by the now-deleted object are no longer pointers to that object. They store the same address, but that address is no longer the address of any object (in fact it may soon be reused as the address of a different object).
This distinction would be more obvious if pointers in C++ behaved like weak references, i.e. as soon as the object is destroyed, all extant pointers to it would immediately be set to 0. (That's the kind of thing considered to be too costly at runtime to impose on all C++ programs, and in fact it is impossible to make it entirely reliable.)
UPDATE: Reading this back nine years later, it's lawyer-ish. I now find your original reaction understandable. To disallow mutation but allow destruction is clearly problematic. The implied contract of const pointers/references is that their existence will act as a block on destruction of the target object, a.k.a. automatic garbage collection.
The usual solution to this is to use almost any other language instead.