references and composition

N

Nick Valeontis

Hmmm, i have been playing around with cpp, but, honestly, I need some help
on this one...

Could someone explain to me why this does work as it does?

************** ************** ************** **************
#include <iostream>
using namespace std;
class Value {
public:
int v;
Value(int value) {
cout << "const!";
v = value;
}
};
class T {
public:
Value& value;

T(Value value):value(value) {

}
};

int main(int argc, char** argv) {
Value v(5);
T t(v);

cout << v.v;
cout << t.value.v;

//t.value.v++; // output is 5555 !!?
v.v++; // output is 5566

cout << v.v;
cout << t.value.v;
}
************** ************** ************** **************

while: ( the difference is on the constructor of T)


************** ************** ************** **************
#include <iostream>
using namespace std;
class Value {
public:
int v;
Value(int value) {
cout << "const!";
v = value;
}
};
class T {
public:
Value& value;

T(Value& value):value(value) {

}
};
int main(int argc, char** argv) {
Value v(5);
T t(v);

cout << v.v;
cout << t.value.v;

//t.value.v++; // output is 5566
v.v++; // output is 5566

cout << v.v;
cout << t.value.v;
}
************** ************** ************** **************


any idea?:/


thanks

-Nick
 
A

Alf P. Steinbach

* Nick Valeontis:
class T {
public:
Value& value;

T(Value value):value(value) {

}

The scope of the formal argument name 'value' starts at its point of declaration.

In the mem-initializer 'value(value)' the first 'value' is a mem-initializer-id.
As such it's looked up in the class scope yielding T::value, and for this the
formal argument's name collision doesn't matter. The second is an ordinary
expression, and so lookup of that name should yield the formal argument.

When the constructor's done it has initialized T::value as a reference to a now
non-existing formal argument, yielding Undefined Behavior when that reference is
used -- which for example means that two different compilers (or even separate
but identical invocations in same program) may produce different results.


Cheers & hth.,

- Alf
 
M

Michael Tsang

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Nick Valeontis said:
Hmmm, i have been playing around with cpp, but, honestly, I need some help
on this one...
You are writing C++, not cpp. CPP is a completely different language called
C Preprocessor.
Could someone explain to me why this does work as it does?

************** ************** ************** **************
#include <iostream>
using namespace std;
class Value {
public:
int v;
Value(int value) {
cout << "const!";
v = value;
}
};
class T {
public:
Value& value;

T(Value value):value(value) {

}
value is *passed by value* to the constructor. In the initialiser, the class
member reference "this->value" is initialised by "value" parameter, which is
an object allocated on the stack of the initialiser. Therefore, this->value
is an object on the stack, which is deallocated as soon as the constructor
finishes. Now, this->value is an object which does not exist, any attempt to
access this->value is undefined behaviour.
};

int main(int argc, char** argv) {
Value v(5);
T t(v);
In this case, you passes the *value* stored inside v, not the object v
itself, because the parameter is passed by value.
cout << v.v;
cout << t.value.v;

//t.value.v++; // output is 5555 !!?
t.value, as mentioned above, is an object which does not exist. You are
trying to access the sub-object t.value.v which lies inside an object which
does not exist, so undefined behaviour is invoked.
v.v++; // output is 5566

cout << v.v;
cout << t.value.v;
}
************** ************** ************** **************

while: ( the difference is on the constructor of T)


************** ************** ************** **************
#include <iostream>
using namespace std;
class Value {
public:
int v;
Value(int value) {
cout << "const!";
v = value;
}
};
class T {
public:
Value& value;

T(Value& value):value(value) {

}
The difference here is "value" is passed by reference. Assuming you passes a
valid object to the constructor, "value" is *the object you've passed in*.
Then you again initialise this->value by reference, therefore, this->value
is the same object as value, also the same object you passed in. When the
constructor finished, this->value becomes the object you passed into the
constructor.
};
int main(int argc, char** argv) {
Value v(5);
T t(v);
In this case, you passed the *object* v into the constructor, because the
parameter is passed by reference. Therefore, the parameter "value" in t.T(v)
is the same object as v, when t.T(v) finishes running, t.value is the same
object as v.
cout << v.v;
cout << t.value.v;

//t.value.v++; // output is 5566
v.v++; // output is 5566

cout << v.v;
cout << t.value.v;
}
************** ************** ************** **************


any idea?:/


thanks

-Nick
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)

iEYEARECAAYFAkr32jAACgkQG6NzcAXitM9XLQCff7yJESSNK1hjpDzJ73QGk0Os
kO8An1KfnWV6ztL6YPOhdtJWoYecUgrx
=aJ2r
-----END PGP SIGNATURE-----
 
N

Nick Valeontis

hmm,

yep, i understand now what is going on.

I'd like to thank you both for the detailed answers!

:)


-Nick
 
C

chad

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1



You are writing C++, not cpp. CPP is a completely different language called
C Preprocessor.







value is *passed by value* to the constructor. In the initialiser, the class
member reference "this->value" is initialised by "value" parameter, which is
an object allocated on the stack of the initialiser. Therefore, this->value
is an object on the stack, which is deallocated as soon as the constructor
finishes. Now, this->value is an object which does not exist, any attempt to
access this->value is undefined behaviour.> };


In this case, you passes the *value* stored inside v, not the object v
itself, because the parameter is passed by value.



t.value, as mentioned above, is an object which does not exist. You are
trying to access the sub-object t.value.v which lies inside an object which
does not exist, so undefined behaviour is invoked.







The difference here is "value" is passed by reference. Assuming you passes a
valid object to the constructor, "value" is *the object you've passed in*..
Then you again initialise this->value by reference, therefore, this->value
is the same object as value, also the same object you passed in. When the
constructor finished, this->value becomes the object you passed into the
constructor.> };

In this case, you passed the *object* v into the constructor, because the
parameter is passed by reference. Therefore, the parameter "value" in t.T(v)
is the same object as v, when t.T(v) finishes running, t.value is the same
object as v.

Does the term *object* mean 'an instance of a class' in this case? Or
does the term *object* mean an unnamed variable?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,745
Messages
2,569,485
Members
44,909
Latest member
DestinyKetoScam

Latest Threads

Top