Topic: C++ seems to allow an implicit const-->non-const conversion under
Author: alfps@start.no ("Alf P. Steinbach")
Date: Thu, 31 Aug 2006 17:26:21 GMT Raw View
* Christoph Schulz:
> Consider following C++ program:
>=20
> #include <iostream>
> using namespace std;
>=20
> struct Test
> {
> Test &nonconst_this;
> int value;
> Test () : nonconst_this (*this), value (1) {}
> void inc () {++value;}
> void inc () const {nonconst_this.inc ();}
> };
>=20
> int main ()
> {
> const Test t;
> cout << t.value << endl; // prints 1
> t.inc ();
> cout << t.value << endl; // prints 2 with the compilers I used
> // (MSVC++ 2005, Comeau 4.3.8 BETA)
> }
>=20
> My question is whether the program produces undefined behaviour or not
> with regard to the current C++ standard.
Formally, yes, because =A77.1.5.1/4: "... any attempt to modify a=20
[non-mutable] const object during its lifetime (3.8) results in=20
undefined behavior".
> As far as I can see this
> program is able to perform a const-->non-const conversion without
> specifying a cast, namely by the use of a non-const reference
> initialized by the constructor. That is alarming because implicit
> const-->non-const conversions are evil. However, provided the program
> above does compile cleanly as it does not violate any diagnosable rule
> (what I assume), I don't see any way to catch the obviously existing
> error at compile time.
Some compilers warn about using 'this' in constructor initialization=20
lists. However, that feature is generally most unwelcome. In practice=20
the programmer using 'this' in an initialization list knows what s/he is=20
doing.
> A possibility would be perhaps to add const constructors with the
> special rule that member initialization is allowed although the "this"
> pointer is of type T const* instead of T*.
>=20
> What do you think?
There's no way to prevent a programmer from shooting her or his own=20
feet, one way or another.
--=20
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: Ron Natalie <ron@spamcop.net>
Date: Thu, 31 Aug 2006 12:38:47 CST Raw View
Christoph Schulz wrote:
> Consider following C++ program:
>
> #include <iostream>
> using namespace std;
>
> struct Test
> {
> Test &nonconst_this;
> int value;
> Test () : nonconst_this (*this), value (1) {}
During the construction of an object, the constness of *this is
turned off (otherwise you could never really initialize a const).
Since you keep a reference (a pointer would have done the same)
to the non-const *this at this point, you are explicitly busting
const.
>
> My question is whether the program produces undefined behaviour or not
> with regard to the current C++ standard.
Changes once the constructor finishes are indeed undefined behavior.
> As far as I can see this
> program is able to perform a const-->non-const conversion without
> specifying a cast, namely by the use of a non-const reference
> initialized by the constructor. That is alarming because implicit
> const-->non-const conversions are evil.
There's nothing implicit. You explicitly violated the rules by leaving
a pointer around to *this outside an appropriate context. A large
number of compilers will actually give you a warning about the use
of the "this" pointer being used during construction like this.
Your solution is unworkable. You would have to allow the this pointer
(or reference to *this) to be passed to other functions (either
explicitly as an argument, or implicitly as being a call to another
non-const non-static member function in the object). These
functions would be succeptable to the same sort of const breaking
if they stored the pointer/reference to this somewhere that persists
past the duration of the construction.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: alfps@start.no ("Alf P. Steinbach")
Date: Thu, 31 Aug 2006 17:37:05 GMT Raw View
* Florin Neamtu:
> The program is not valid C++ as the "this" pointer cannot be used in
> the initializer list.
Please quote the relevant chapter and verse.
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: ron@spamcop.net (Ron Natalie)
Date: Thu, 31 Aug 2006 20:22:21 GMT Raw View
Florin Neamtu wrote:
> The program is not valid C++ as the "this" pointer cannot be used in
> the initializer list.
Yes it is.
> In the scope of the initializer list the object is not yet constructed
> and any reference to it is invalid; such your code passes a pointer to
> an unconstructed object and the result is undefined according to the
> standard.
Is not.
While it is dangerous to be passing around pointers to objects still
under construction to unwary recipients, it is not prohibited.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: kristov@arcor.de (Christoph Schulz)
Date: Thu, 31 Aug 2006 16:05:05 GMT Raw View
Consider following C++ program:
#include <iostream>
using namespace std;
struct Test
{
Test &nonconst_this;
int value;
Test () : nonconst_this (*this), value (1) {}
void inc () {++value;}
void inc () const {nonconst_this.inc ();}
};
int main ()
{
const Test t;
cout << t.value << endl; // prints 1
t.inc ();
cout << t.value << endl; // prints 2 with the compilers I used
// (MSVC++ 2005, Comeau 4.3.8 BETA)
}
My question is whether the program produces undefined behaviour or not
with regard to the current C++ standard. As far as I can see this
program is able to perform a const-->non-const conversion without
specifying a cast, namely by the use of a non-const reference
initialized by the constructor. That is alarming because implicit
const-->non-const conversions are evil. However, provided the program
above does compile cleanly as it does not violate any diagnosable rule
(what I assume), I don't see any way to catch the obviously existing
error at compile time.
A possibility would be perhaps to add const constructors with the
special rule that member initialization is allowed although the "this"
pointer is of type T const* instead of T*.
What do you think?
Regards,
Christoph
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]