Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Simple const-related question

Reply
Thread Tools

Simple const-related question

 
 
nsdevelop12@yahoo.com
Guest
Posts: n/a
 
      02-18-2008
Is "const Object* pA = new Object(1)" the same as "const Object A(1)"
in terms of creating const objects that should not be modified through
cast-to-non-const pointers. See the following example:


const int* createInt()
{
return new int(1);
}

void myFunc( const int* const_param )
{
cout << "const_param == " << *const_param << endl;

int *non_const_param = const_cast<int*>( const_param );
*non_const_param = 999;

cout << "const_param == " << *const_param << endl;
}

int main(int argc, char* argv[])
{
int a = 1;
const int b = 1;
int* c = new int(1);
const int* d = new int(1);
const int* e = createInt();

myFunc( &a ); // ok
myFunc( &b ); // bad
myFunc( c ); // ok
myFunc( d ); // bad (?)
myFunc( e ); // bad (?)

return 0;
}

 
Reply With Quote
 
 
 
 
nsdevelop12@yahoo.com
Guest
Posts: n/a
 
      02-18-2008
On Feb 18, 6:30 pm, (E-Mail Removed) wrote:
> Is "const Object* pA = new Object(1)" the same as "const Object A(1)"
> in terms of creating const objects that should not be modified through
> cast-to-non-const pointers. See the following example:
>
> const int* createInt()
> {
> return new int(1);
>
> }
>
> void myFunc( const int* const_param )
> {
> cout << "const_param == " << *const_param << endl;
>
> int *non_const_param = const_cast<int*>( const_param );
> *non_const_param = 999;
>
> cout << "const_param == " << *const_param << endl;
>
> }
>
> int main(int argc, char* argv[])
> {
> int a = 1;
> const int b = 1;
> int* c = new int(1);
> const int* d = new int(1);
> const int* e = createInt();
>
> myFunc( &a ); // ok
> myFunc( &b ); // bad
> myFunc( c ); // ok
> myFunc( d ); // bad (?)
> myFunc( e ); // bad (?)
>
> return 0;
>
> }


I guess my real question is what does "new int(1)" or "new MyObject()"
create - is it always non-const object, or does it depend on the
context as in the following:

MyObject *p1 = new MyObject(); // p1 is non-const
const MyObject *p2 = new MyObject(); // p2 is ???

What about:

MyObject* myFunction()
{
return new MyObject();
}

MyObject* p1 = myFunction(); // p1 is non-const
const MyObject *p2 = myFunction(); // p2 is ???
 
Reply With Quote
 
 
 
 
Daniel T.
Guest
Posts: n/a
 
      02-19-2008
On Feb 18, 5:45*pm, (E-Mail Removed) wrote:
> On Feb 18, 6:30 pm, (E-Mail Removed) wrote:
>
>
>
> > Is "const Object* pA = new Object(1)" the same as "const Object A(1)"
> > in terms of creating const objects that should not be modified through
> > cast-to-non-const pointers. *See the following example:

>
> > const int* createInt()
> > {
> > * * return new int(1);

>
> > }

>
> > void myFunc( const int* const_param )
> > {
> > * * cout << "const_param == " << *const_param << endl;

>
> > * * int *non_const_param = const_cast<int*>( const_param );
> > * * *non_const_param = 999;

>
> > * * cout << "const_param == " << *const_param << endl;

>
> > }

>
> > int main(int argc, char* argv[])
> > {
> > * * * * * int *a = 1;
> > * * const int *b = 1;
> > * * * * * int* c = new int(1);
> > * * const int* d = new int(1);
> > * * const int* e = createInt();

>
> > * * myFunc( &a ); // ok
> > * * myFunc( &b ); // bad
> > * * myFunc( *c ); // ok
> > * * myFunc( *d ); // bad (?)
> > * * myFunc( *e ); // bad (?)

>
> > * * return 0;

>
> > }

>
> I guess my real question is what does "new int(1)" or "new MyObject()"
> create - is it always non-const object, or does it depend on the
> context as in the following:
>
> MyObject *p1 = new MyObject(); // p1 is non-const
> const MyObject *p2 = new MyObject(); // p2 is ???
>
> What about:
>
> MyObject* myFunction()
> {
> * * return new MyObject();
>
> }
>
> MyObject* p1 = myFunction(); // p1 is non-const
> const MyObject *p2 = myFunction(); // p2 is ???


Get out of the Java habit of putting () after the class name when
calling new. I'm pretty sure that "new Object();" and "new Object;" do
different things.

In answer to your question, the object returned by new is inherently
non-const, but once placed in a const pointer, non-const functions can
no longer be called on that object through that pointer. That doesn't
mean the object is const though, note for example:

Object* o = new Object;
const Object* o2 = o;

o->non_const_func(); // perfectly OK even though the object is being
held in a pointer to const elsewhere.

 
Reply With Quote
 
Jeff Schwab
Guest
Posts: n/a
 
      02-19-2008
Daniel T. wrote:
> On Feb 18, 5:45 pm, (E-Mail Removed) wrote:
>> On Feb 18, 6:30 pm, (E-Mail Removed) wrote:
>>
>>
>>
>>> Is "const Object* pA = new Object(1)" the same as "const Object A(1)"
>>> in terms of creating const objects that should not be modified through
>>> cast-to-non-const pointers. See the following example:
>>> const int* createInt()
>>> {
>>> return new int(1);
>>> }
>>> void myFunc( const int* const_param )
>>> {
>>> cout << "const_param == " << *const_param << endl;
>>> int *non_const_param = const_cast<int*>( const_param );
>>> *non_const_param = 999;
>>> cout << "const_param == " << *const_param << endl;
>>> }
>>> int main(int argc, char* argv[])
>>> {
>>> int a = 1;
>>> const int b = 1;
>>> int* c = new int(1);
>>> const int* d = new int(1);
>>> const int* e = createInt();
>>> myFunc( &a ); // ok
>>> myFunc( &b ); // bad
>>> myFunc( c ); // ok
>>> myFunc( d ); // bad (?)
>>> myFunc( e ); // bad (?)
>>> return 0;
>>> }


I believe the last two examples are OK. "int const* p = new int()" is
fundamentally different from "int const i = 5", because the type of the
object pointed to may be in a read-only area of memory in the second
case, but not in the first. I'm not sure why you would ever need this,
though; if you need a non-const pointer to a dynamically allocated
object, why not just hang onto it in the first place? Unnecessary
const_casts defeat the purpose of declaring a pointer-to-const in the
first place.

>> I guess my real question is what does "new int(1)" or "new MyObject()"
>> create - is it always non-const object, or does it depend on the
>> context as in the following:
>>
>> MyObject *p1 = new MyObject(); // p1 is non-const
>> const MyObject *p2 = new MyObject(); // p2 is ???
>>
>> What about:
>>
>> MyObject* myFunction()
>> {
>> return new MyObject();
>>
>> }
>>
>> MyObject* p1 = myFunction(); // p1 is non-const
>> const MyObject *p2 = myFunction(); // p2 is ???

>
> Get out of the Java habit of putting () after the class name when
> calling new. I'm pretty sure that "new Object();"


Allocates a default-constructed Object.

> and "new Object;" do


Allocates a potentially uninitialized object, if Object is a POD type.

http://www.research.att.com/~bs/bs_faq2.html#malloc

I don't usually use the parentheses, either, but I guess I probably
should. I also don't usually allocate objects directly with new.

> different things.
>
> In answer to your question, the object returned by new is inherently
> non-const, but once placed in a const pointer, non-const functions can
> no longer be called on that object through that pointer. That doesn't
> mean the object is const though, note for example:
>
> Object* o = new Object;
> const Object* o2 = o;
>
> o->non_const_func(); // perfectly OK even though the object is being
> held in a pointer to const elsewhere.


Agreed.
 
Reply With Quote
 
Kira Yamato
Guest
Posts: n/a
 
      02-19-2008
On 2008-02-18 20:05:51 -0500, Jeff Schwab <(E-Mail Removed)> said:

> Daniel T. wrote:
>> On Feb 18, 5:45 pm, (E-Mail Removed) wrote:
>>> On Feb 18, 6:30 pm, (E-Mail Removed) wrote:
>>>
>>> [...]

>> Get out of the Java habit of putting () after the class name when
>> calling new. I'm pretty sure that "new Object();"

>
> Allocates a default-constructed Object.
>
>> and "new Object;" do

>
> Allocates a potentially uninitialized object, if Object is a POD type.
>
> http://www.research.att.com/~bs/bs_faq2.html#malloc
>
> I don't usually use the parentheses, either, but I guess I probably
> should. I also don't usually allocate objects directly with new.
>
>> different things.


Just curious. Instead of directly using new, what do you usually use
to allocate objects?

--

// kira

 
Reply With Quote
 
nsdevelop12@yahoo.com
Guest
Posts: n/a
 
      02-19-2008
On Feb 18, 9:05 pm, Jeff Schwab <(E-Mail Removed)> wrote:
> Daniel T. wrote:
> > On Feb 18, 5:45 pm, (E-Mail Removed) wrote:
> >> On Feb 18, 6:30 pm, (E-Mail Removed) wrote:

>
> >>> Is "const Object* pA = new Object(1)" the same as "const Object A(1)"
> >>> in terms of creating const objects that should not be modified through
> >>> cast-to-non-const pointers. See the following example:
> >>> const int* createInt()
> >>> {
> >>> return new int(1);
> >>> }
> >>> void myFunc( const int* const_param )
> >>> {
> >>> cout << "const_param == " << *const_param << endl;
> >>> int *non_const_param = const_cast<int*>( const_param );
> >>> *non_const_param = 999;
> >>> cout << "const_param == " << *const_param << endl;
> >>> }
> >>> int main(int argc, char* argv[])
> >>> {
> >>> int a = 1;
> >>> const int b = 1;
> >>> int* c = new int(1);
> >>> const int* d = new int(1);
> >>> const int* e = createInt();
> >>> myFunc( &a ); // ok
> >>> myFunc( &b ); // bad
> >>> myFunc( c ); // ok
> >>> myFunc( d ); // bad (?)
> >>> myFunc( e ); // bad (?)
> >>> return 0;
> >>> }

>
> I believe the last two examples are OK. "int const* p = new int()" is
> fundamentally different from "int const i = 5", because the type of the
> object pointed to may be in a read-only area of memory in the second
> case, but not in the first. I'm not sure why you would ever need this,
> though; if you need a non-const pointer to a dynamically allocated
> object, why not just hang onto it in the first place? Unnecessary
> const_casts defeat the purpose of declaring a pointer-to-const in the
> first place.
>
>
>
> >> I guess my real question is what does "new int(1)" or "new MyObject()"
> >> create - is it always non-const object, or does it depend on the
> >> context as in the following:

>
> >> MyObject *p1 = new MyObject(); // p1 is non-const
> >> const MyObject *p2 = new MyObject(); // p2 is ???

>
> >> What about:

>
> >> MyObject* myFunction()
> >> {
> >> return new MyObject();

>
> >> }

>
> >> MyObject* p1 = myFunction(); // p1 is non-const
> >> const MyObject *p2 = myFunction(); // p2 is ???

>
> > Get out of the Java habit of putting () after the class name when
> > calling new. I'm pretty sure that "new Object();"

>
> Allocates a default-constructed Object.
>
> > and "new Object;" do

>
> Allocates a potentially uninitialized object, if Object is a POD type.
>
> http://www.research.att.com/~bs/bs_faq2.html#malloc
>
> I don't usually use the parentheses, either, but I guess I probably
> should. I also don't usually allocate objects directly with new.
>
> > different things.

>
> > In answer to your question, the object returned by new is inherently
> > non-const, but once placed in a const pointer, non-const functions can
> > no longer be called on that object through that pointer. That doesn't
> > mean the object is const though, note for example:

>
> > Object* o = new Object;
> > const Object* o2 = o;

>
> > o->non_const_func(); // perfectly OK even though the object is being
> > held in a pointer to const elsewhere.

>
> Agreed.


Thanks for your help. I'm really trying to avoid the caveat described
here:

http://www.parashift.com/c++-faq-lit...html#faq-18.13

Using the author's example, I want to make sure that "const Set *s =
new S(...)" is not the same as "const Set s". Although the author
doesn't fully explain why changing "s" in the latter case through an
explicit non-const pointer cast (e.g. "Set *ps =
const_cast<Set*>(&s)") is a problem, I'm assuming its because the
compiler was free to optimize by substituting the value of "s"
wherever it was used in code. If that's the case, then I guess the
former case works because "s" is a pointer to dynamic memory that is
allocated at runtime. But I'm no expert in compilers, so I just
wanted to be sure there were not other tricks at play (like what if
"Set" had an inline constructor or something).
 
Reply With Quote
 
Jeff Schwab
Guest
Posts: n/a
 
      02-19-2008
Kira Yamato wrote:
> On 2008-02-18 20:05:51 -0500, Jeff Schwab <(E-Mail Removed)> said:
>
>> Daniel T. wrote:
>>> On Feb 18, 5:45 pm, (E-Mail Removed) wrote:
>>>> On Feb 18, 6:30 pm, (E-Mail Removed) wrote:
>>>>
>>>> [...]
>>> Get out of the Java habit of putting () after the class name when
>>> calling new. I'm pretty sure that "new Object();"

>>
>> Allocates a default-constructed Object.
>>
>>> and "new Object;" do

>>
>> Allocates a potentially uninitialized object, if Object is a POD type.
>>
>> http://www.research.att.com/~bs/bs_faq2.html#malloc
>>
>> I don't usually use the parentheses, either, but I guess I probably
>> should. I also don't usually allocate objects directly with new.
>>
>>> different things.

>
> Just curious. Instead of directly using new, what do you usually use to
> allocate objects?


Either the stack (sorry, "auto" storage) or one of the standard
containers. If I have dynamically allocated objects, I generally have
to store pointers to them somewhere anyway, so I let standard containers
deal with managing their lifetimes. For example, if I'll need an
unknown quantity of Foos, I just create a std::list<Foo> and use its
elements. Inserting or deleting list elements does not invalidate
pointers to the other elements.

Allan Holub has an interesting (very opinionated) take on
object-oriented design, which he summarizes in his "Getters and Setters
are Evil" article, and which he describes in depth in the APress book
"Holub on Patterns." The idea is essentially that rather than pulling
data from various sources into a controller object, he tries to push
commands to objects that already have access to the data. The down-side
is that the code implementing a given application is spread all over
creation. The up-side for me has been that because I'm pushing rather
than pulling, object methods rarely need to return pointers to anything.

If an object A knows how to create a Foo, and object B has to do
something with the Foo, A can usually just creates the Foo on the stack,
and pass it to Foo. Suppose the main "controller" function needs an
object of type Foo, but only object a knows how to create a Foo. Rather
than requesting a Foo from object a, the controller function passes a
Receiver object to object a's Foo creation method. Object a creates the
Foo on the stack, then passes it to the receiver. The receiver does
whatever is necessary with the Foo before returning, and the Foo is
automatically destroyed as the stack unwinds back to the controller
function. It's very much like passing an operation to a standard
algorithm like std::for_each, or passing an output iterator to
std::transform.

Suppose main() wants to print a Foo, but only object a can make a Foo.
The "pull" approach might look like this:

/* Pulling a Foo. */
#include <iostream>
#include <vector>

struct Foo { };

std:stream& operator<<(std:stream& out, Foo const& foo) {
return out << "Foo at " << &foo << '\n';
}

struct A {

~A() {
/* Delete any items in foo_. */
// ...
}

Foo* create_foo() {
foo_.push_back(new Foo);
return foo_.back();
}

private:
std::vector<Foo*> foo_;
};

int main() {
A a;

/* Somebody has to keep track of each foo. */
Foo* foo = a.create_foo();

std::cout << *foo;
}

The "push" approach gets rid of the dynamic memory allocation entirely.
A new static type has to be introduced (the receiver), but you no
longer need a container to keep track of the dynamically allocated
objects. In effect, the run-time stack is the container.

/* Pushing a Foo. */
#include <iostream>

struct Foo { };

std:stream& operator<<(std:stream& out, Foo const& foo) {
return out << "Foo at " << &foo << '\n';
}

struct Printing_receiver {

Printing_receiver(std:stream& out):
out_(&out) { }

template<typename T>
void operator()(T const& t) const {
*out_ << t;
}

private:
std:stream* const out_;
};

struct A {
template<typename Foo_receiver>
void create_foo(Foo_receiver const& receiver) {
Foo foo;
receiver(foo);
}
};

int main() {
A a;
a.create_foo(Printing_receiver(std::cout));
}

As long as the creation functions are re-entrant, you can do this as
much as you want, or at least until you run out of stack space.
 
Reply With Quote
 
Jeff Schwab
Guest
Posts: n/a
 
      02-19-2008
http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:
> On Feb 18, 9:05 pm, Jeff Schwab <(E-Mail Removed)> wrote:
>> Daniel T. wrote:
>>> On Feb 18, 5:45 pm, (E-Mail Removed) wrote:
>>>> On Feb 18, 6:30 pm, (E-Mail Removed) wrote:
>>>>> Is "const Object* pA = new Object(1)" the same as "const Object A(1)"
>>>>> in terms of creating const objects that should not be modified through
>>>>> cast-to-non-const pointers. See the following example:
>>>>> const int* createInt()
>>>>> {
>>>>> return new int(1);
>>>>> }
>>>>> void myFunc( const int* const_param )
>>>>> {
>>>>> cout << "const_param == " << *const_param << endl;
>>>>> int *non_const_param = const_cast<int*>( const_param );
>>>>> *non_const_param = 999;
>>>>> cout << "const_param == " << *const_param << endl;
>>>>> }
>>>>> int main(int argc, char* argv[])
>>>>> {
>>>>> int a = 1;
>>>>> const int b = 1;
>>>>> int* c = new int(1);
>>>>> const int* d = new int(1);
>>>>> const int* e = createInt();
>>>>> myFunc( &a ); // ok
>>>>> myFunc( &b ); // bad
>>>>> myFunc( c ); // ok
>>>>> myFunc( d ); // bad (?)
>>>>> myFunc( e ); // bad (?)
>>>>> return 0;
>>>>> }

>> I believe the last two examples are OK. "int const* p = new int()" is
>> fundamentally different from "int const i = 5", because the type of the
>> object pointed to may be in a read-only area of memory in the second
>> case, but not in the first. I'm not sure why you would ever need this,
>> though; if you need a non-const pointer to a dynamically allocated
>> object, why not just hang onto it in the first place? Unnecessary
>> const_casts defeat the purpose of declaring a pointer-to-const in the
>> first place.
>>
>>
>>
>>>> I guess my real question is what does "new int(1)" or "new MyObject()"
>>>> create - is it always non-const object, or does it depend on the
>>>> context as in the following:
>>>> MyObject *p1 = new MyObject(); // p1 is non-const
>>>> const MyObject *p2 = new MyObject(); // p2 is ???
>>>> What about:
>>>> MyObject* myFunction()
>>>> {
>>>> return new MyObject();
>>>> }
>>>> MyObject* p1 = myFunction(); // p1 is non-const
>>>> const MyObject *p2 = myFunction(); // p2 is ???
>>> Get out of the Java habit of putting () after the class name when
>>> calling new. I'm pretty sure that "new Object();"

>> Allocates a default-constructed Object.
>>
>>> and "new Object;" do

>> Allocates a potentially uninitialized object, if Object is a POD type.
>>
>> http://www.research.att.com/~bs/bs_faq2.html#malloc
>>
>> I don't usually use the parentheses, either, but I guess I probably
>> should. I also don't usually allocate objects directly with new.
>>
>>> different things.
>>> In answer to your question, the object returned by new is inherently
>>> non-const, but once placed in a const pointer, non-const functions can
>>> no longer be called on that object through that pointer. That doesn't
>>> mean the object is const though, note for example:
>>> Object* o = new Object;
>>> const Object* o2 = o;
>>> o->non_const_func(); // perfectly OK even though the object is being
>>> held in a pointer to const elsewhere.

>> Agreed.

>
> Thanks for your help. I'm really trying to avoid the caveat described
> here:
>
> http://www.parashift.com/c++-faq-lit...html#faq-18.13
>
> Using the author's example, I want to make sure that "const Set *s =
> new S(...)" is not the same as "const Set s". Although the author
> doesn't fully explain why changing "s" in the latter case through an
> explicit non-const pointer cast (e.g. "Set *ps =
> const_cast<Set*>(&s)") is a problem, I'm assuming its because the
> compiler was free to optimize by substituting the value of "s"
> wherever it was used in code. If that's the case, then I guess the
> former case works because "s" is a pointer to dynamic memory that is
> allocated at runtime. But I'm no expert in compilers, so I just
> wanted to be sure there were not other tricks at play (like what if
> "Set" had an inline constructor or something).


Why do you need the const_cast? If the method really does change the
object, then the method should be non-const. If the method is
conceptually const, but you need to do a little internal housekeeping on
some data member (e.g. to update a cache), then you can make the member
mutable.
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      02-19-2008
On Feb 19, 1:47 am, "Daniel T." <(E-Mail Removed)> wrote:
> On Feb 18, 5:45 pm, (E-Mail Removed) wrote:
> > On Feb 18, 6:30 pm, (E-Mail Removed) wrote:


[...]
> > MyObject* p1 = myFunction(); // p1 is non-const
> > const MyObject *p2 = myFunction(); // p2 is ???


> Get out of the Java habit of putting () after the class name
> when calling new. I'm pretty sure that "new Object();" and
> "new Object;" do different things.


If Object has a class type with a user defined constructor, they
do exactly the same thing. Otherwise, new Object() probably
does what you want most of the time.

> In answer to your question, the object returned by new is inherently
> non-const, but once placed in a const pointer, non-const functions can
> no longer be called on that object through that pointer. That doesn't
> mean the object is const though, note for example:


> Object* o = new Object;
> const Object* o2 = o;


> o->non_const_func(); // perfectly OK even though the object is being
> held in a pointer to const elsewhere.


And to answer the original question, casting away const on the
pointer, and then accessing it, is fully defined behavior.
Technically, you're allowed to allocate a const object, e.g.
"new const Object", but in practice, I don't think any
implementation will make a difference---undefined behavior or
not, the code will actually work exactly as if the object hadn't
been declared const (which, of course, is a permitted behavior
for undefined behavior).

--
James Kanze (GABI Software) email:(E-Mail Removed)
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      02-19-2008
On Feb 19, 2:05 am, Jeff Schwab <(E-Mail Removed)> wrote:

[...]
> >> MyObject* p1 = myFunction(); // p1 is non-const
> >> const MyObject *p2 = myFunction(); // p2 is ???


> > Get out of the Java habit of putting () after the class name when
> > calling new. I'm pretty sure that "new Object();"


> Allocates a default-constructed Object.


> > and "new Object;" do


> Allocates a potentially uninitialized object, if Object is a POD type.


> http://www.research.att.com/~bs/bs_faq2.html#malloc


> I don't usually use the parentheses, either, but I guess I
> probably should.


I don't usually use them either, because I learned C++ before
this distinction existed. But then, I don't usually dynamically
allocate objects which don't have a user defined constructor, so
it doesn't make a difference.

> I also don't usually allocate objects directly with new.


What do you allocate them with, then?

--
James Kanze (GABI Software) email:(E-Mail Removed)
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Plz, a simple answer to a simple question about IP addresses MeekiMoo Computer Support 0 07-28-2009 08:10 AM
Simple region code question... simple answer?? joseph.greer@gmail.com DVD Video 7 01-26-2007 09:07 PM
Simple Question - Simple Answer? Daniel Frey XML 4 01-12-2005 04:25 PM
Re: Simple Simple question!!! Kevin Spencer ASP .Net 0 06-25-2004 05:25 PM
Re: Simple Simple question!!! ashelley@inlandkwpp.com ASP .Net 0 06-25-2004 04:18 PM



Advertisments