Why Can't I pass an Address As a Reference? - c++

I have a function that takes a pointer as a reference argument, but I cannot pass in &my_variable to the function. The error I am receiving is cannot convert parameter from my_class* to my_class*&, using VS2010.
Why is this not allowed?
class my_class
{
public:
my_class();
my_class(my_class* &parent);
};
--
int main()
{
my_class a;
my_class b(&a); // Not legal
// ---
my_class a;
my_class* a_ptr = &a;
my_class b(a); // Legal
// ---
my_class* a = new my_class;
my_class* b = new my_class(a); // Legal
}

The result of an address-of expression is an rvalue. Therefore, you cannot bind it to reference-to-nonconst.
It also makes no sense. It's like saying int a; &a = 12; Obviously you cannot change the address of the variable a.
Instead, you want this:
int a;
int * p = &a;
mutate_me(p); // declared as mutate_me(int * &);
If the function does not need to mutate the pointer, pass it either by const-reference or by value.

Think about situation when you write something like
void foo(bar*& ptr) {
ptr = new bar;
}
bar b;
foo(&b);

Informally, a method expecting a parameter by reference expects that it gets passed something that can be legally placed on the left side of an assignment statement (sometimes called an "lvalue").
int main()
{
my_class a;
my_class b(&a); // Not legal: &a = 0; would be illegal because you can't change an address of a variable.
// ---
my_class a;
my_class* a_ptr = &a;
my_class b(a_ptr); // Legal: You've declared a_ptr on the stack and its value (what it points to) can be changed. The address of a_ptr would not be changeable though.
// ---
my_class* a = new my_class;
my_class* b = new my_class(a); // Legal: Again, this is on the stack and `a` could point to something else, but its own address won't be changed.
}
In this case, it's worth pointing out that in most cases, passing a pointer by value is inexpensive and will work. If you really need the pointer to be modifiable (passed by reference), then you need to pass an lvalue.
Another option is to have the reference be const. Then I believe you can pass rvalues just fine.

Related

C++ pointer to a class member in the same class [Conceptual]?

`
class A{
public:
int x;
A* p;
};
int main(){
A obj1 = new A(); //no suitable constructor exists to convert from "A *" to "A"
A *obj2 = new A(); //Works fine
return 0;
}
`
Why is an object of class A declared as a pointer to that class, by default?
In other words, why does obj1 doesn't work but *obj2 does.
The new operator returns a pointer, so you can assign it only to a variable of pointer type.
You can use A obj1 = A();, which will simply call the constructor (without allocating dynamic memory, which is what new does) and return a A, not a A*.
No. Why is an object of class A declared as a pointer to that class, by default? Is incorrect. An object of class is just an object of that type and no pointer there.
The keyword new is used to allocate dynamic memory for a pointer. That is a memory must be cleaned up manually when you're done with it otherwise you will face a memory leak.
A* pObj = new A; // ok
A obj = new A; // error
A obj = *pObj; // ok:
Above obj is just an instance of class A and pObj is a pointer to an object of class A so inside the pointer there's the address of the object so to access it we dereference the pointer:
obj = *pObj = 0; // De-referencing pObj and assigning the value it points to to obj.
Finally clean up:
delete pObj; // ok
delete obj; // error

C++ pointer and address clarification in relation to the current object

So far to my understanding, when defining a pointer variable, we are allocating space in RAM for that variable.
int *p;
Would define a space in RAM. Then we assign a memory address to that pointer using `&variable'.
I'm looking over at an example on: *this vs this in C++
The code is:
#include <iostream>
class Foo
{
public:
Foo()
{
this->value = 0;
}
Foo get_copy()
{
return *this;
}
Foo& get_copy_as_reference()
{
return *this;
}
Foo* get_pointer()
{
return this;
}
void increment()
{
this->value++;
}
void print_value()
{
std::cout << this->value << std::endl;
}
private:
int value;
};
int main()
{
Foo foo;
foo.increment();
foo.print_value();
foo.get_copy().increment();
foo.print_value();
foo.get_copy_as_reference().increment();
foo.print_value();
foo.get_pointer()->increment();
foo.print_value();
return 0;
}
I don't understand what the purpose of putting the * operator in front Foo* get_copy() and Foo* get_pointer() does. Why do I get an error if I removed the * from the Foo* functions while returning this not *this?
edit:
Also, why is:
foo.get_copy().increment();
foo.print_value();
yielding 1 not 2?
I don't understand what the purpose of putting the * operator in front Foo* get_copy() and Foo* get_pointer() does
Foo* get_pointer()
Foo* is a pointer that points to Foo object.
this is also a pointer that implicitly bind to the calling object of the member function. That's why the return type of those functions are Foo* not Foo.
The * is part of the type. So int means type int, and
int* type pointer to int. If the function returns pointer
to int, it is int* foo(), and if it retu rns a pointer to
Foo, it is Foo* Foo::get_pointer().
The definition reserves space for the defined object. A
declaration doesn't reserve any space, and definitions of things
that aren't objects (e.g. references or functions) don't reserve
any space either, at least not that you can see. (Obviously, a
function does exist somewhere in memory, and in many cases, the
compiler will need space as well for its implementation of a
reference. But they are invisible within the scope of C++.)
this, is always a pointer in C++, though you don't mention it explicitly anywhere. So while returning a this pointer, should use Foo*
this is actually an implicit object passed during function call, which is a pointer to the object which calls the function
It seems that you have changed the code from the example that you refer to so that get_copy() no longer returns a copy.
There are 2 ways of using * in your code example. One is for type declaration and the other is the dereferencing operator.
First the type declarations:
int *p means declaring p as a variable of type "pointer to an int".
Foo *get_pointer() means that the function get_pointer will return a value of type "pointer to a Foo object".
Now the dereferencing:
*p means "the value that p points to".
int a = 42;
int *p; // p is of type "pointer to an int"
p = &a; // set p to the address of a (p now "points to" a)
a = 117; // change the value of a
int x = *p; // set x to the value that p points to (which is a) - x will be 117
this is just a pointer to the object. *this means "the object that this points to". In your example this is of type Foo* (pointer to a Foo object) while *this is of type Foo (a Foo object).
"this" is a pointer.
you want to return a pointer to the instance (a specific allocated object).
Foo* get_pointer(){
return this;
}
or you want to return a pointer to the copy, allocate a new object.
//need to implement the copy here
Foo* get_copy(){
return this;
}
and not to the reference (address of the instance). this is why you need to return the pointer.

Referencing const objects/pointers in C++

There's something I don't quite understand with how references are handled in C++:
B objB = B(); // Regular B object
const B &refConstObjB = objB; // Reference to const B object
B* ptrB = new B(); // Regular pointer to B
B* const &refPtrConstB = ptrB; // Reference to const pointer to B
All of the above compiles just fine. However the following doesn't:
const B* &refConstPtrB = ptrB; // Reference to pointer to const B
Considering both the object and the pointer were declared as non-const, why can I reference the object as a const object, but can't do the same with the pointer?
Just to note: A const reference does not imply a const object.
It simply means an object that is read-only through that reference. So whether or not an object is const, you can have a read-only reference or pointer to it.
Now, if what you mentioned were allowed, you could say refConstPtrB = pointer_to_some_const_B, and then mutate that object through ptrB, which would violate the const-ness of the pointer's target.
The reason for this error is that you can put a hole in the type system with it. Consider the following code:
const B dontChangeMe;
B* ptrB = new B();
/* This step is NOT legal. */
const B* &refConstPtrB = ptrB;
/* Uh oh! I now have ptrB pointing at dontChangeMe! */
refConstPtrB = &dontChangeMe;
Consequently, you can't do the assignment that you marked.
Hope this helps!

Using class pointers vs instance

What I don't understand is what is the difference between using a pointer to a class and generating a new instance of it. It's just for performance? Here I made a class and made m the pointer to the class and n the instance of the class.
And another question: can i make a pointer the class and use another constructor? like myClass* p(7); p->afis(); ?
#include <iostream>
using namespace std;
class myClass
{
int a;
public:
myClass(void);
myClass(int);
void afis();
~myClass(void);
};
myClass::myClass(void)
{
a = 5;
}
myClass::myClass(int nr)
{
a = nr;
}
void myClass::afis()
{
cout << a;
}
myClass::~myClass()
{
}
int main()
{
myClass* m; //<--
m->afis();
myClass n(7); //<--
n.afis();
cin.get();
}
myClass* m;
is just an pointer to the type myClass it does not point to any valid object, dereferecing such a pointer is Undefined Behavior.
An Undefined Behavior means that your program is invalid and it may seem to work or it may crash or it may show any weird behavior, all safe bets are off. So just because your program works does not mean it is safe and it will always work.
To write a valid program you will have to make the pointer point to a valid object.
For example:
myClass obj;
myClass*m = &obj;
In the second case:
myClass n(7);
It creates an object n of the type myClass by calling the constructor of myClass which takes one argument of the type int.
This is a valid way of creating an object.
can i make a pointer the class and use another constructor
Making a pointer doesn't call a constructor. The pointer is uninitialized until you set it to the address of some object (maybe a brand new object created with new).
myClass* m; //<--
m->afis();
This is undefined behavior, you have a wild pointer because m hasn't been initialized.
Better:
std::unique_ptr<myClass> m(new myClass(constructor, args, here));
m->afis();

create an instance for a pointer in other scopes

I have two methods to create an instance for a pointer.
But one of them will fail.
class A {
public:
int num;
};
void testPointer1(A* a){
a = new A();
a->num = 10;
}
A* testPointer2(){
A* a = new A();
a->num = 10;
return a;
}
void testPointer() {
A* a1 = NULL;
testPointer1(a1); // this one fails
//cout << a1->num << endl; // segmentation fault
A* a2 = NULL;
a2 = testPointer2();
cout << a2->num << endl;
}
why is testPointer1 wrong?
The syntax is valid, but it doesn't do what you want because testPointer1() is operating on a copy of the pointer, not the actual pointer itself. So when you assign the address to the newly allocated object, it gets assigned to the copy, not to the original a1 pointer.
Because of this, the address is lost and you get a memory leak. Also, since the original a1 pointer was never modified in the first place, you attempted to dereference a null pointer, which is a bad thing.
I'd say testPointer2() is the better way to do it, but if you want testPointer1() to work, try this:
void testPointer1(A*& a)
{
a = new A();
a->num = 10;
}
The parameter type indicates "a reference to a pointer to A." That way, instead of a copy of the pointer being passed, a reference to the original pointer will be passed. A C++ reference is an alias to another object. So whatever you do on the alias, it gets performed on the original object.
Extra notes:
Note that the parentheses in new A(); are actually significant and their presence or absence makes a difference.
Also note that you must manually delete all new'ed objects after you're done with them, or you will get a leak. Typically you would wrap the pointer in its own class and implement RAII or use a smart pointer such as Boost's smart pointers or auto_ptr, for proper memory management and exception safety.
If you're going to set the value of num on initialization, why not create a constructor?
class A
{
public:
A(int n) : num(n) {}
int GetNum() const { return num; }
private:
int num;
};
void testPointer1(A*& a)
{
a = new A(10);
}
A* testPointer2()
{
return new A(10);
}
// auto_ptr example, see link in second note above
std::auto_ptr<A> testPointer3()
{
return auto_ptr<A>(new A(10));
}
The testPointer1 functions works on a copy of the provided pointer : modifications to a in testPointer1 are not reflected to the caller.
It's exactly like in this simpler example :
void testInt1(int i)
{
i++;
}
void testInt()
{
int i = 0;
testInt1(i);
// i is still 0
}
If you want the change in testInt1 to be reflected to the caller, you have to pass either a pointer or reference to i (and not just the value of i). The same solution can be applied to your specific case, though one could argue that pointers to pointer and references to pointer are not really a best practice.
Is this homework ?
This seems to be obvious:
formal parameters are saved on the stack & restored after method/function call.
then whatever f(type x), manipulating x inside the function/method won't change it's value outside of the function.
even if type is a pointer type.
the only way to make x change inside a function is to tell it is modifiable through references or pointer to type.
in your case :
A* a1 =NULL
call to your method won't change value of a1 outside of testPointer1
so a1 will still be NULL after the call.