|
|
|
|
||||||
![]() |
|
|
LinkBack | Outils de la discussion |
|
|
#1 |
|
Messages: n/a
Hébergeur: |
I remember there was a thread a while back that was talking about using the
return value of a function as a reference where I had thought the reference would become invalidated because it was a temporary but it was stated that it would not. This has come up in an irc channel but I can not find the original thread, nor can I get any code to work. Foo& Bar( int Val ) { return Foo( Val ); } Will not work, can not convert Foo to Foo& Foo Bar( int Val ) { return Foo( Val ); } int main() { Foo& Inst = Bar( 10 ); } Does not work, same thing, can not convert Foo to Foo&. Foo& Bar(int Val ) { Foo Temp( Val ); return Foo( Val ); } int main() { Foo& Inst = Bar( 10 ); } Does not work, checking the value of Val_ later shows garbage data indicating the reference has become invalidated (as expected). Can anyone remember the case where a temp value returned from a function can be used as a reference and not invalidated immediately? -- Jim Langston tazmaster@rocketmail.com |
|
|
|
#2 |
|
Messages: n/a
Hébergeur: |
On 2007-12-25 15:00:36 -0500, "Jim Langston" <tazmaster@rocketmail.com> said:
> I remember there was a thread a while back that was talking about using the > return value of a function as a reference where I had thought the reference > would become invalidated because it was a temporary but it was stated that > it would not. This has come up in an irc channel but I can not find the > original thread, nor can I get any code to work. > > Foo& Bar( int Val ) > { > return Foo( Val ); > } > > Will not work, can not convert Foo to Foo& > > Foo Bar( int Val ) > { > return Foo( Val ); > } > > int main() > { > Foo& Inst = Bar( 10 ); > } > > Does not work, same thing, can not convert Foo to Foo&. > > Foo& Bar(int Val ) > { > Foo Temp( Val ); > return Foo( Val ); > } > > int main() > { > Foo& Inst = Bar( 10 ); > } > > Does not work, checking the value of Val_ later shows garbage data > indicating the reference has become invalidated (as expected). Can anyone > remember the case where a temp value returned from a function can be used as > a reference and not invalidated immediately? Foo Bar(int x) { return Foo(x); } int main() { const Foo &foo = Bar(10); return 0; } -- -kira |
|
|
|
#3 |
|
Messages: n/a
Hébergeur: |
On Dec 25, 3:00 pm, "Jim Langston" <tazmas...@rocketmail.com> wrote:
> Foo& Bar( int Val ) > { > return Foo( Val ); > > } > > Will not work, can not convert Foo to Foo& > Should work, but not a very useful thing to do as local copy dies immediately. > Foo Bar( int Val ) > { > return Foo( Val ); > > } > > int main() > { > Foo& Inst = Bar( 10 ); > > } > > Does not work, same thing, can not convert Foo to Foo&. > Should also work. Something else is going on as that syntax is compiling fine in my compiler. > Foo& Bar(int Val ) > { > Foo Temp( Val ); > return Foo( Val ); > > } > I think you meant to return Temp, no? That too should work, but as with #1, isn't very useful. > int main() > { > Foo& Inst = Bar( 10 ); > > } > > Does not work, checking the value of Val_ later shows garbage data > indicating the reference has become invalidated (as expected). Can anyone > remember the case where a temp value returned from a function can be used as > a reference and not invalidated immediately? Here's some thoughts: Foo g_foo; class Y { protected: Foo _x; // instance (or member) variable static Foo _y; // class instance variable (i.e., a static) public: Foo& GetFoo(); Foo& GetFoo2(); }; Foo& Y::GetFoo() { return _x; } Foo& Y::GetFoo2() { static Foo localStaticFoo; // global to all instances of Y but only accessible within GetFoo2. return localStaticFoo; } int main() { Y y; Foo& foo = y.GetFoo(); Foo& foo2 = y.GetFoo2(); Foo& foo3 = g_foo; } A reference has to 'point' to a preexisting instance of something (i.e., must be initialized to something upon declaration-- note that this also includes any references that you might have as class members which must be initted in your constructors' init lists). In your case where that instance was local, it satisfied your compiler, but obviously didn't have any use as it was deleted underneath you when the func exited. So, you have to couple that idea with a longer living object (such as class member, static member, or global). |
|
|
|
#4 |
|
Messages: n/a
Hébergeur: |
On 2007-12-26 06:01, johanatan wrote:
> On Dec 25, 3:00 pm, "Jim Langston" <tazmas...@rocketmail.com> wrote: >> Foo& Bar( int Val ) >> { >> return Foo( Val ); >> >> } >> >> Will not work, can not convert Foo to Foo& >> > > Should work, but not a very useful thing to do as local copy dies > immediately. Should not work, a reference can not bind to a rvalue. >> Foo Bar( int Val ) >> { >> return Foo( Val ); >> >> } >> >> int main() >> { >> Foo& Inst = Bar( 10 ); >> >> } >> >> Does not work, same thing, can not convert Foo to Foo&. >> > > Should also work. Something else is going on as that syntax is > compiling fine in my compiler. Get a new compiler. Once again, you can not bind a reference to a rvalue. >> Foo& Bar(int Val ) >> { >> Foo Temp( Val ); >> return Foo( Val ); >> >> } >> > > I think you meant to return Temp, no? That too should work, but as > with #1, isn't very useful. Invoking undefined behaviour I would think. -- Erik Wikström |
|
|
|
#5 |
|
Messages: n/a
Hébergeur: |
On Dec 26, 6:33 am, Erik Wikström <Erik-wikst...@telia.com> wrote:
> On 2007-12-26 06:01, johanatan wrote: > > > On Dec 25, 3:00 pm, "Jim Langston" <tazmas...@rocketmail.com> wrote: > >> Foo& Bar( int Val ) > >> { > >> return Foo( Val ); > > >> } > > >> Will not work, can not convert Foo to Foo& > > > Should work, but not a very useful thing to do as local copy dies > > immediately. > > Should not work, a reference can not bind to a rvalue. > Ok, you're right. I just tried this again in Ch (a C++ interpreter) -- apparently the method wasn't being called before and so wasn't compiled. > >> Does not work, same thing, can not convert Foo to Foo&. > > > Should also work. Something else is going on as that syntax is > > compiling fine in my compiler. > > Get a new compiler. Once again, you can not bind a reference to a rvalue. > This is certainly an interesting design decision of C++. I suspect it was a 'safety' feature built in, but I prefer languages to be more flexible by inferring as much as possible from context. What is the danger of binding to an r-value? A value is a value (and if you were thinking in purely functional terms, this is just a transformation that happens in one line instead of two). Does it really things to declare the Foo on one line return it instead of the constructor call? Substitution (i.e., rewriting) is the name of the game. Why prevent this level of compaction? --Jonathan |
|
|
|
#6 |
|
Messages: n/a
Hébergeur: |
On 27 ÄÅË, 04:19, johanatan <johana...@gmail.com> wrote:
> This is certainly an interesting design decision of C++. šI suspect it > was a 'safety' feature built in, but I prefer languages to be more > flexible by inferring as much as possible from context. šWhat is the > danger of binding to an r-value? šA value is a value (and if you were > thinking in purely functional terms, this is just a transformation > that happens in one line instead of two). šDoes it really things > to declare the Foo on one line return it instead of the constructor > call? šSubstitution (i.e., rewriting) is the name of the game. šWhy > prevent this level of compaction? We prefer choosing language after the problem to be solved, not before. If you `prefer' languages, then go ahead, write all your programs on perl which surely allows you to return valid reference to local objects. As far as i understand, that's not a `safety' feature, like `const' is not it as well. It's just a way to imbue pre- and postconditions on our *source* code. I mean, C++ compiler is so strict because it encourages programmers to write a program verifiable to some extent. A program driven by underlying ideas, by underlying concepts and restrictions (not all! just a couple of, but this little effort makes its benifit) of their models. But not vice versa which as you seem to misunderstand is not the right way of writing programs. That leads to a nice and usefult thing: if your program doesn't fit your model's requirements it won't compile. Which, in turn, saves time spent on debugging. |
|
|
|
#7 |
|
Messages: n/a
Hébergeur: |
On 2007-12-27 02:19, johanatan wrote:
> On Dec 26, 6:33 am, Erik Wikström <Erik-wikst...@telia.com> wrote: >> On 2007-12-26 06:01, johanatan wrote: >> >> > On Dec 25, 3:00 pm, "Jim Langston" <tazmas...@rocketmail.com> wrote: >> >> Foo& Bar( int Val ) >> >> { >> >> return Foo( Val ); >> >> >> } >> >> >> Will not work, can not convert Foo to Foo& >> >> > Should work, but not a very useful thing to do as local copy dies >> > immediately. >> >> Should not work, a reference can not bind to a rvalue. >> > > Ok, you're right. I just tried this again in Ch (a C++ interpreter) > -- apparently the method wasn't being called before and so wasn't > compiled. > >> >> Does not work, same thing, can not convert Foo to Foo&. >> >> > Should also work. Something else is going on as that syntax is >> > compiling fine in my compiler. >> >> Get a new compiler. Once again, you can not bind a reference to a rvalue. >> > > This is certainly an interesting design decision of C++. I suspect it > was a 'safety' feature built in, but I prefer languages to be more > flexible by inferring as much as possible from context. What is the > danger of binding to an r-value? Consider the following code: int& r = 5; r = 6; If I can bind a reference to a value I can also change that value. But that is not how a reference works, a reference is a alias for an object not an object on its own. Therefore a reference can not bind to a rvalue. > A value is a value (and if you were thinking in purely functional > terms, this is just a transformation that happens in one line instead > of two). But C++ is not a functional language, thinking in functional terms will lead you astray. > Does it really things to declare the Foo on one line return it > instead of the constructor call? Substitution (i.e., rewriting) is > the name of the game. Why prevent this level of compaction? Because when you declare the object first and then returns it you have an lvalue, which you can bind a reference to. -- Erik Wikström |
|
|
|
#8 |
|
Messages: n/a
Hébergeur: |
"johanatan" <johanatan@gmail.com> wrote in message
news:8e1e678a-bee2-499d-a8fc-ec14185c149a@r60g2000hsc.googlegroups.com... > What is the danger of binding to an r-value? If it is possible to bind a reference to an rvalue, then there is no basis for the compiler to reject: int x = 0, y = 0; cin >> (x + y); |
|
|
|
#9 |
|
Messages: n/a
Hébergeur: |
On Dec 27, 6:49 am, Erik Wikström <Erik-wikst...@telia.com> wrote:
> > This is certainly an interesting design decision of C++. I suspect it > > was a 'safety' feature built in, but I prefer languages to be more > > flexible by inferring as much as possible from context. What is the > > danger of binding to an r-value? > > Consider the following code: > > int& r = 5; > > r = 6; > > If I can bind a reference to a value I can also change that value. But > that is not how a reference works, a reference is a alias for an object > not an object on its own. Therefore a reference can not bind to a rvalue. > Ok, so I suspect it was decided early on that the easiest way to prevent 'changing' a reference was to disallow setting it to *any* r- value? That surely simplifies writing a compiler for the language, but seems like a pretty arbitrary restriction to place on programmers (and it seems possible to me to make a compiler that could differentiate between an initial setting and subsequent 'changes'). And, another question that follows naturally-- 'Why aren't references allowed to be changed to begin with?' If they were, then the r-value problem goes away and then the integration of boost's 'shared_ptr' functionality would be much more seamless at this time. I really would have preferred some sort of new syntax to the language itself instead of tacking on another lib as part of the 'standard'. For instance, you could use: int^ x; to represent a 'smart' ptr in the same way that 'int&' is a reference. > > A value is a value (and if you were thinking in purely functional > > terms, this is just a transformation that happens in one line instead > > of two). > > But C++ is not a functional language, thinking in functional terms will > lead you astray. > Well, when you write: int x = g(f(y)); you're doing 'functional' stuff (aside from the storage in a variable). My point was that the practice of programming boils down to 'rewrites', or substitutions or transformations. Even when in an imperative language, much of the job is about writing one thing to represent another (i.e., symbols). > > Does it really things to declare the Foo on one line return it > > instead of the constructor call? Substitution (i.e., rewriting) is > > the name of the game. Why prevent this level of compaction? > > Because when you declare the object first and then returns it you have > an lvalue, which you can bind a reference to. > Yea, but, once again, that's only because of the (as far as I can tell) arbitrary decision to disallow setting to r-value. I think there's a misunderstanding here between what is 'required' by the syntax of the language and the requirements imposed upon the language by external forces (at least in my mind). --Jonathan |
|
|
|
#10 |
|
Messages: n/a
Hébergeur: |
On Dec 27, 10:16 am, "Andrew Koenig" <a...@acm.org> wrote:
> "johanatan" <johana...@gmail.com> wrote in message > > news:8e1e678a-bee2-499d-a8fc-ec14185c149a@r60g2000hsc.googlegroups.com... > > > What is the danger of binding to an r-value? > > If it is possible to bind a reference to an rvalue, then there is no basis > for the compiler to reject: > > int x = 0, y = 0; > cin >> (x + y); Hmm... that's interesting. One possible way to deal with that is to let it put the input into an unnamed variable (which would be inaccessible unless you expose some sort of global environment a la python). If you think that type of programming error is so likely that this restriction is a net gain, then I guess it's a win. I'm just not completely convinced yet. :-) --Jonathan |
|
|
|
#11 |
|
Messages: n/a
Hébergeur: |
On 2007-12-27 20:47, johanatan wrote:
> On Dec 27, 6:49 am, Erik Wikström <Erik-wikst...@telia.com> wrote: > >> > This is certainly an interesting design decision of C++. I suspect it >> > was a 'safety' feature built in, but I prefer languages to be more >> > flexible by inferring as much as possible from context. What is the >> > danger of binding to an r-value? >> >> Consider the following code: >> >> int& r = 5; >> >> r = 6; >> >> If I can bind a reference to a value I can also change that value. But >> that is not how a reference works, a reference is a alias for an object >> not an object on its own. Therefore a reference can not bind to a rvalue. >> > > Ok, so I suspect it was decided early on that the easiest way to > prevent 'changing' a reference was to disallow setting it to *any* r- > value? You can never change a reference, only the object it refers to. > That surely simplifies writing a compiler for the language, > but seems like a pretty arbitrary restriction to place on programmers > (and it seems possible to me to make a compiler that could > differentiate between an initial setting and subsequent 'changes'). I think it makes sense, you can not create a reference to an object that can no be changed. Call it a safety mechanism that prevents users from making stupid mistakes. Of course that does not prevent one from referring to r-values, but you need to have a const reference (to ensure that the user does not modify the rvalue through the reference). > And, another question that follows naturally-- 'Why aren't references > allowed to be changed to begin with?' If they were, then the r-value > problem goes away and then the integration of boost's 'shared_ptr' > functionality would be much more seamless at this time. If you could change a reference then you would have a pointer, and we already have those. And as we all know pointers are not very safe to play with. Not sure what you mean with shared_ptr would be more seam- lessly integrated, though. > I really would have preferred some sort of new syntax to the language > itself instead of tacking on another lib as part of the 'standard'. > For instance, you could use: > > int^ x; > > to represent a 'smart' ptr in the same way that 'int&' is a reference. Personally I prefer to keep the stuff in the language to a minimum and have a library which provides the stuff I need, but that is just me. If you want a language where everything (well, at least a lot) is hidden from the programmer with syntactic sugar try C#. >> > A value is a value (and if you were thinking in purely functional >> > terms, this is just a transformation that happens in one line instead >> > of two). >> >> But C++ is not a functional language, thinking in functional terms will >> lead you astray. >> > > Well, when you write: > > int x = g(f(y)); > > you're doing 'functional' stuff (aside from the storage in a > variable). In a functional language the above would likely mean that g() was a function taking a function which takes one argument as argument, while in C++ it means that g() is called with the value returned from f(x). > My point was that the practice of programming boils down > to 'rewrites', or substitutions or transformations. Even when in an > imperative language, much of the job is about writing one thing to > represent another (i.e., symbols). Yes, programming is all about collecting information and then transforming it into something else. >> > Does it really things to declare the Foo on one line return it >> > instead of the constructor call? Substitution (i.e., rewriting) is >> > the name of the game. Why prevent this level of compaction? >> >> Because when you declare the object first and then returns it you have >> an lvalue, which you can bind a reference to. >> > > Yea, but, once again, that's only because of the (as far as I can > tell) arbitrary decision to disallow setting to r-value. I think > there's a misunderstanding here between what is 'required' by the > syntax of the language and the requirements imposed upon the language > by external forces (at least in my mind). I think that Andrew Koenig's example makes it quite clear why you can not bind a reference to an r-value, in many cases it simply does not make sense. I have two questions for you: 1. Are you aware of and understand the difference between a reference and a const reference? 2. Can you give an example of when it would be useful to bind a reference to a r-value? -- Erik Wikström |
|
|
|
#12 |
|
Messages: n/a
Hébergeur: |
On 27 Dec, 23:58, Erik Wikström <Erik-wikst...@telia.com> wrote:
> 2. Can you give an example of when it would be useful to bind a > reference to a r-value? void retransfer(Object& x) { x.timestamp=now(); x.transferred=true; buf b = allocate_superbuffer(sizeof(x)); copy_to_superbuffer(b,x); } retransfer (a); //we want to mark Object a as transferred and pass it along retransfer (b+c); //we want to pass result of b+c along and do not care much what happens to temporary variable of Object type the result of operator+ was assigned to. Yes, i know. I can easilly write Object d=b+c; retransfer(d); but why? What if i really *don't care* and moreover i *don't want* to take care of where result of this sum will go? Why should i write one more line of code (!) if i really don't need it? A man reading my code would surely be surprised, `Why does he need this d variable??' Well, one can make more life-bound example, but this one shows that sometimes we should really sacrifice a hamster for the compiler to get an elephant past the corner. |
|
|
|
#13 |
|
Messages: n/a
Hébergeur: |
Erik Wikström wrote:
> 2. Can you give an example of when it would be useful to bind a > reference to a r-value? Consider: std::vector<int> v; ... v.swap( std::vector<int>() ); // fails swap( v, std::vector<int>() ); // fails std::vector<int>().swap( v ); // succeeds It is especially bad that the middle line fails. The rules of [8.3.5/5] make it difficult to define swap()-like functions for proxy classes. E.g., it is somewhat tricky to have a line like row_swap( A.row(1), A.row(2) ); do a row-swap in a matrix class and be const-correct. Another surprise caused by the rules of [8.3.5/5] (and frequently coming up in this group in various disguises) is this: int main ( void ) { std: fstream( "test.001" ) << std::dec << "hello world!" << '\n';std: fstream( "test.002" ) << "hello world!" << '\n';} On my machine, this creates files like so: test.001: hello world! test.002: 0x8048a01 Best Kai-Uwe Bux |
|
|
|
#14 |
|
Messages: n/a
Hébergeur: |
On 2007-12-27 18:19:17 -0500, jkherciueh@gmx.net said:
> Erik Wikström wrote: > >> 2. Can you give an example of when it would be useful to bind a >> reference to a r-value? > > Consider: > > std::vector<int> v; > ... > v.swap( std::vector<int>() ); // fails > swap( v, std::vector<int>() ); // fails > std::vector<int>().swap( v ); // succeeds > > It is especially bad that the middle line fails. The rules of [8.3.5/5] make > it difficult to define swap()-like functions for proxy classes. E.g., it is > somewhat tricky to have a line like > > row_swap( A.row(1), A.row(2) ); > > do a row-swap in a matrix class and be const-correct. > > > Another surprise caused by the rules of [8.3.5/5] (and frequently coming up > in this group in various disguises) is this: > > int main ( void ) { > std: fstream( "test.001" ) << std::dec << "hello world!" << '\n';> std: fstream( "test.002" ) << "hello world!" << '\n';> } > > On my machine, this creates files like so: > > test.001: hello world! > test.002: 0x8048a01 o.O This is truly unexpected! I'm guessing this is an instance of calling the member version of operator<< verses the nonmember version. In the first line with "test.001", the 1st call to the member version of operator<<(std::dec) returns a reference to an object, which then can be used in the nonmember version of operator<<(ostream &, const char *). However, in the second line with "test.002", the expression std: fstream("test.002") is a temporary object which cannot be boundto the 1st parameter of the nonmember version operator<<(ostream &, const char *). Hence, it resorts to some member version of operator<< which converted const char * to some integer. Wow. When I thought I've seen the worst, I'm being surprise more and more to see that C++ truly has some totally-unobvious gotcha's. I hope the next revision of C++ will address some of these strange codes. -- -kira |
|
|
|
#15 |
|
Messages: n/a
Hébergeur: |
On Dec 27, 3:58 pm, Erik Wikström <Erik-wikst...@telia.com> wrote:
> >> If I can bind a reference to a value I can also change that value. But > >> that is not how a reference works, a reference is a alias for an object > >> not an object on its own. Therefore a reference can not bind to a rvalue. > > > Ok, so I suspect it was decided early on that the easiest way to > > prevent 'changing' a reference was to disallow setting it to *any* r- > > value? > > You can never change a reference, only the object it refers to. > I understand. But, the question was: is the prevention of setting a reference to *any* r-value an easy way for a compiler to enforce the 'set only once' rule for references, and if so, was that the rationale for the set-once rule? > > And, another question that follows naturally-- 'Why aren't references > > allowed to be changed to begin with?' If they were, then the r-value > > problem goes away and then the integration of boost's 'shared_ptr' > > functionality would be much more seamless at this time. > > If you could change a reference then you would have a pointer, and we > already have those. And as we all know pointers are not very safe to > play with. Not sure what you mean with shared_ptr would be more seam- > lessly integrated, though. > But, the point of a reference is to hide that you have a pointer. The restriction that it be set only once just seems somewhat arbitrary. After all, in Java and C#, languages where references (and for that matter, reference-counted smart ptrs) can be set multiple times (and even to NULL). > > I really would have preferred some sort of new syntax to the language > > itself instead of tacking on another lib as part of the 'standard'. > > For instance, you could use: > > > int^ x; > > > to represent a 'smart' ptr in the same way that 'int&' is a reference. > > Personally I prefer to keep the stuff in the language to a minimum and > have a library which provides the stuff I need, but that is just me. If > you want a language where everything (well, at least a lot) is hidden > from the programmer with syntactic sugar try C#. Well, my problem with all the libs for doing this stuff in C++ is the klunkiness of the syntax. Just take a look inside <functional> (STL header) sometime to see lots of cool features that are added with klunky syntax. > In a functional language the above would likely mean that g() was a > function taking a function which takes one argument as argument, while > in C++ it means that g() is called with the value returned from f(x). > Not necessarily. In a purely functional language, the x wouldn't be specified. And, once it is specified, the 'f' that operates on that specific x comes into existence and the 'g' can subsequently operate on it. Having a 'g' that can operate on many types of 'f' was not the point of my example (maybe it was a bad example). But, the point was that in C++, as well as functional langs, functions transform input (whether the input is a function or not) and their output can be piped right into another function, hence resulting, in essence, to a 'transliteration'. It will certainly be a nice addition to C++ when first-class functions arrive. > > 1. Are you aware of and understand the difference between a reference > and a const reference? > Yes. With a const reference, you can only call 'const' member functions (assuming its an object). With a non-const reference, you can modify at will. Just like anything else const or non-const I suppose. > 2. Can you give an example of when it would be useful to bind a > reference to a r-value? I can't. But, just scrolling down, the other examples posted are very nice! In general, every restriction that a lang places is going to have unintended side effects and there's always a trade-off between flexibility/power and 'safeness'. In some situations, you just end up writing code to satisfy a compiler when you know better. ;-) I don't think that is the case with 'const-correctness' (as another poster mentioned) of C++, but even that requirement might have corner cases that I am missing right now. Const-correctness and setting an r- value into a reference are in two different leagues in my opinion. --Jonathan |
|
|
|
#16 |
|
Messages: n/a
Hébergeur: |
On Dec 27, 3:04 am, Pavel Shved <Pavel.Sh...@gmail.com> wrote:
> We prefer choosing language after the problem to be solved, not > before. If you `prefer' languages, then go ahead, write all your > programs on perl which surely allows you to return valid reference to > local objects. > I wasn't speaking with any 'problem' in mind except that of specifying for a computing machine that work which it shall do. I actually learned to program with C++ and have since moved to Perl and other 'dynamic' languages (Python and Ruby), and others, and am now back with C++. I've gotta say that moving to those dynamic langs was definitely a 'freeing' experience, but even better than those, from a purely theoretical point of view, in my opinion, is my current interest--Haskell. It has all the benefits of a strongly typed language and the terseness of functional langs. For me, the closer to the math a lang is, the more concise and clean it is, the more elegant and beautiful. After all, programming for the sake of programming should not be discounted. The only rationale for using C++ that I've heard lately is for performance as there are many other modern O-O langs to choose from (some are even compiled and can perform at least as well such as Objective-C, but that really only applies if your platform is Apple). > As far as i understand, that's not a `safety' feature, like `const' is > not it as well. It's just a way to imbue pre- and postconditions on > our *source* code. I mean, C++ compiler is so strict because it > encourages programmers to write a program verifiable to some extent. > A program driven by underlying ideas, by underlying concepts and > restrictions (not all! just a couple of, but this little effort makes > its benifit) of their models. But not vice versa which as you seem to > misunderstand is not the right way of writing programs. > > That leads to a nice and usefult thing: if your program doesn't fit > your model's requirements it won't compile. Which, in turn, saves > time spent on debugging. Yea, I definitely agree with this point (especially as it applies to const-correctness and type-safety). But, even those have unintended side effects which are a pain to work through at times. Not everything that is done to satisfy compilers (in fact, a substantial amount, I think) actually saves time or prevents bugs. --Jonathan |
|
|
|
#17 |
|
Messages: n/a
Hébergeur: |
On 2007-12-28 08:51, johanatan wrote:
> On Dec 27, 3:58 pm, Erik Wikström <Erik-wikst...@telia.com> wrote: >> >> If I can bind a reference to a value I can also change that value. But >> >> that is not how a reference works, a reference is a alias for an object >> >> not an object on its own. Therefore a reference can not bind to a rvalue. >> >> > Ok, so I suspect it was decided early on that the easiest way to >> > prevent 'changing' a reference was to disallow setting it to *any* r- >> > value? >> >> You can never change a reference, only the object it refers to. >> > > I understand. But, the question was: > > is the prevention of setting a reference to *any* r-value an easy way > for a compiler to enforce the 'set only once' rule for references, and > if so, was that the rationale for the set-once rule? No, even if you could bind a reference to a r-value you would not be able to rebind it later on. That is the way references were designed to work. >> > And, another question that follows naturally-- 'Why aren't references >> > allowed to be changed to begin with?' If they were, then the r-value >> > problem goes away and then the integration of boost's 'shared_ptr' >> > functionality would be much more seamless at this time. >> >> If you could change a reference then you would have a pointer, and we >> already have those. And as we all know pointers are not very safe to >> play with. Not sure what you mean with shared_ptr would be more seam- >> lessly integrated, though. >> > > But, the point of a reference is to hide that you have a pointer. The > restriction that it be set only once just seems somewhat arbitrary. > After all, in Java and C#, languages where references (and for that > matter, reference-counted smart ptrs) can be set multiple times (and > even to NULL). That is because the references of Java and C# are more like pointers than C++ references, theonly similarity between Java/C# references and C++ references is the name. The references in C++ are a totally different concept, in C++ a reference is an alias for an object, if you think of it that way you can see why they may not be reseated. >> 1. Are you aware of and understand the difference between a reference >> and a const reference? >> > > Yes. With a const reference, you can only call 'const' member > functions (assuming its an object). With a non-const reference, you > can modify at will. Just like anything else const or non-const I > suppose. And a const reference can bind to an r-value. >> 2. Can you give an example of when it would be useful to bind a >> reference to a r-value? > > I can't. But, just scrolling down, the other examples posted are very > nice! Ah, I am starting to see your point (I might be a bit slow, but I usually get there). You might want to check out the Rvalue references, which will be part of the next version of C++. I think it could be used to solve all the problems you, Kai-Uwe Bux, and Pavel Shved mentioned. A quick overview: http://www.open-std.org/jtc1/sc22/wg...006/n2027.html -- Erik Wikström |
|
|
|
#18 |
|
Messages: n/a
Hébergeur: |
On Dec 28, 3:37am, Erik Wikström <Erik-wikst...@telia.com> wrote:
> > But, the point of a reference is to hide that you have a pointer. The > > restriction that it be set only once just seems somewhat arbitrary. > > After all, in Java and C#, languages where references (and for that > > matter, reference-counted smart ptrs) can be set multiple times (and > > even to NULL). > > That is because the references of Java and C# are more like pointers > than C++ references, theonly similarity between Java/C# references and > C++ references is the name. The references in C++ are a totally > different concept, in C++ a reference is an alias for an object, if you > think of it that way you can see why they may not be reseated. > That just isn't true (on both technical and conceptual levels). Technically, a reference in C++ is just a ptr with syntactic sugar to allow using it just like the object itself instead of dereferencing the ptr (or using the -> operator). Conceptually, they are the same in the two languages (barring the restrictions already mentioned that C ++ enforces). The only differences I'm aware of between C#/Java and C+ + with regards to references are: -. Java references are 'smart' references (i.e., ref counted). -. Java references can be assigned to NULL. -. Java references can be set multiple times (and have no restrictions against setting to r-values). Under the skin, they are both ptrs (while the Java variant has an additional ref count and possibly other bookeeping-related (i.e., garbage collector) metadata). I suspect that the reference idea was a step forward for C++ from C (adding only the syntactic sugar over a regular ptr) and that the designers of Java took the idea one step further. --Jonathan |
|
|
|
#19 |
|
Messages: n/a
Hébergeur: |
On Dec 27, 1:34pm, Pavel Shved <Pavel.Sh...@gmail.com> wrote:
> void retransfer(Object& x) > { > x.timestamp=now(); > x.transferred=true; > buf b = allocate_superbuffer(sizeof(x)); > copy_to_superbuffer(b,x); > > } > > retransfer (a); //we want to mark Object a as transferred and pass > it along > retransfer (b+c); //we want to pass result of b+c along and do not > care much what happens to temporary variable of Object type the result > of operator+ was assigned to. > Well, if C++ will allow binding an r-value to a const reference (something I haven't verified yet, but makes sense), then you could factor out the part of retransfer that modifies the object from the part that simply copies it. Such as: void copyToSuperBuf(const Object& o) { buf b = allocate_superbuffer(sizeof(o)); copy_to_superbuffer(b,o); } void retransfer(Object& o) { o.timestamp=now(); o.transferred=true; copyToSuperBuf(o); } but that doesn't preclude there being another example that couldn't be broken up this way I suppose. --Jonathan |
|
|
|
#20 |
|
Messages: n/a
Hébergeur: |
johanatan <johanatan@gmail.com> writes:
> On Dec 28, 3:37Âam, Erik Wikström <Erik-wikst...@telia.com> wrote: > > > But, the point of a reference is to hide that you have a pointer. ÂThe > > > restriction that it be set only once just seems somewhat arbitrary. > > > After all, in Java and C#, languages where references (and for that > > > matter, reference-counted smart ptrs) can be set multiple times (and > > > even to NULL). > > > > That is because the references of Java and C# are more like pointers > > than C++ references, theonly similarity between Java/C# references and > > C++ references is the name. The references in C++ are a totally > > different concept, in C++ a reference is an alias for an object, if you > > think of it that way you can see why they may not be reseated. > > > > That just isn't true (on both technical and conceptual levels). No, *that* just isn't true (on both technical and conceptual levels). Eric is exactly right: references are aliases for existing objects. Full stop. > Technically, a reference in C++ is just a ptr with syntactic sugar > to allow using it just like the object itself instead of > dereferencing the ptr (or using the -> operator). No indeed. Pointers can be reseated, can be null, and take a (platform-specific) number of bytes. References cannot be reseated, cannot be "null" (although they can be invalid), and don't have a size. The compiler may *implement* references internally as pointers, but that's irrelevent to this discussion. > Conceptually, they are the same in the two languages (barring the > restrictions already mentioned that C ++ enforces). I think they were *supposed* to be conceptually the same in Java and in C++, but it didn't really work out that way. > -. Java references are 'smart' references (i.e., ref counted). > -. Java references can be assigned to NULL. > -. Java references can be set multiple times (and have no restrictions > against setting to r-values). Which are all things you can do with C++ *pointers*, and cannot be done with C++ *references*. Which is what Eric said, and which I reiterated. > Under the skin, they are both ptrs (while the Java variant has an > additional ref count and possibly other bookeeping-related (i.e., > garbage collector) metadata). Under the skin, C++ references are C++ references, period. > I suspect that the reference idea was a step forward for C++ from C > (adding only the syntactic sugar over a regular ptr) and that the > designers of Java took the idea one step further. I'd suggest that Java took the idea one step backwards, but that's a different debate. :-) -- Dave Steffen - Software Engineer 4 Numerica Corporation (www.numerica.us <http://www.numerica.us/> ) |
|
|
|
#21 |
|
Messages: n/a
Hébergeur: |
On Dec 28, 2:32pm, Dave Steffen <dgstef...@numerica.us> wrote: > johanatan <johana...@gmail.com> writes: > > On Dec 28, 3:37am, Erik Wikström <Erik-wikst...@telia.com> wrote: > > > > But, the point of a reference is to hide that you have a pointer. The > > > > restriction that it be set only once just seems somewhat arbitrary. > > > > After all, in Java and C#, languages where references (and for that > > > > matter, reference-counted smart ptrs) can be set multiple times (and > > > > even to NULL). > > > > That is because the references of Java and C# are more like pointers > > > than C++ references, theonly similarity between Java/C# references and > > > C++ references is the name. The references in C++ are a totally > > > different concept, in C++ a reference is an alias for an object, if you > > > think of it that way you can see why they may not be reseated. > > > That just isn't true (on both technical and conceptual levels). > > No, *that* just isn't true (on both technical and conceptual > levels). Eric is exactly right: references are aliases for existing > objects. Full stop. > If that's true, why |