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
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
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.
> 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.
> 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.
> "Nick Valeontis" <mouh...@frGGmail.gr[replace G to e]> wrote:
>> 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
>> 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
> "Nick Valeontis" <mouh...@frGGmail.gr[replace G to e]> wrote:
> > 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.
> > 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