 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Matthias Hofmann Guest
|
Posted: Sat Oct 25, 2003 8:33 am Post subject: Error C2440 when allocating array of pointers |
|
|
Hello,
I get an error C2440 when I compile the following code on VC++ 6.0:
int main( void )
{
const int** p1 = new int*[20]; // Error: Cannot convert from 'int ** '
to 'const int ** '
const int** p2 = new const int*[20]; // Works fine.
return 0;
}
Usually it is ok to assign a pointer to a non-constant object to a pointer
to a constant object. Is this compliant with the standard and if so, why?
Regards,
Matthias
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Thomas Maeder Guest
|
Posted: Sun Oct 26, 2003 4:58 am Post subject: Re: Error C2440 when allocating array of pointers |
|
|
"Matthias Hofmann" <hofmann (AT) anvil-soft (DOT) com> writes:
| Quote: | I get an error C2440 when I compile the following code on VC++ 6.0:
int main( void )
{
const int** p1 = new int*[20]; // Error: Cannot convert from 'int ** '
to 'const int ** '
const int** p2 = new const int*[20]; // Works fine.
return 0;
}
Usually it is ok to assign a pointer to a non-constant object to a pointer
to a constant object. Is this compliant with the standard and if so, why?
|
This is a FAQ:
See http://www.parashift.com/c++-faq-lite/const-correctness.html#faq-18.15
or http://www.comeaucomputing.com/techtalk/#deconstutoh
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Siemel Naran Guest
|
Posted: Sun Oct 26, 2003 5:07 am Post subject: Re: Error C2440 when allocating array of pointers |
|
|
"Matthias Hofmann" <hofmann (AT) anvil-soft (DOT) com> wrote
| Quote: | const int** p1 = new int*[20]; // Error: Cannot convert from 'int **
'
to 'const int ** '
Usually it is ok to assign a pointer to a non-constant object to a pointer
to a constant object. Is this compliant with the standard and if so, why?
|
But what you're doing is assigning a pointer to a pointer to a non-constant
object to a pointer to a pointer to a const object. This is illegal per the
standard. See http://www.jamesd.demon.co.uk/csc/faq.html#C1 for more
details. Here's the reasoning
const int i =1;
int * p;
int * * pp = &p;
const int * * cpp = pp; // suppose this were legal
* cpp = &i;
*p = 2; // oops: changing const object!
If you really must do it, use const_cast (a strange use of const_cast to add
const), but in your case you can just use your second version.
| Quote: | const int** p2 = new const int*[20]; // Works fine.
|
--
+++++++++++
Siemel Naran
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Dhruv Guest
|
Posted: Sun Oct 26, 2003 5:15 am Post subject: Re: Error C2440 when allocating array of pointers |
|
|
On Sat, 25 Oct 2003 04:33:49 -0400, Matthias Hofmann wrote:
| Quote: | Hello,
I get an error C2440 when I compile the following code on VC++ 6.0:
int main( void )
{
const int** p1 = new int*[20]; // Error: Cannot convert from 'int ** '
to 'const int ** '
const int** p2 = new const int*[20]; // Works fine.
return 0;
}
Usually it is ok to assign a pointer to a non-constant object to a pointer
to a constant object. Is this compliant with the standard and if so, why?
|
Try this:
typedef int* pint;
int main()
{
const pint* p1 = new int*[20];
}
Regards,
-Dhruv.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Ivan Vecerina Guest
|
Posted: Sun Oct 26, 2003 5:16 am Post subject: Re: Error C2440 when allocating array of pointers |
|
|
Hi Matthias,
"Matthias Hofmann" <hofmann (AT) anvil-soft (DOT) com> wrote
| Quote: | I get an error C2440 when I compile the following code on VC++ 6.0:
int main( void )
{
const int** p1 = new int*[20]; // Error: Cannot convert from 'int **
'
to 'const int ** '
.....
Usually it is ok to assign a pointer to a non-constant object to a pointer
to a constant object. Is this compliant with the standard and if so, why?
|
Yes, because of the classic problem which is decomposed below:
int* pi = 0;
int** ppi = π
const int** ppci = ppi; // illegal ... see why below <XX>
const int ci = 5;
*ppci = &ci; // oho... by storing a const int* into pi,
// this effectively casts the const out
**ppi = 4; // this now modifies ci => UNDEFINED BEHAVIOR
Basically, if the <XX> statement were legal, it would allow
the constness of some objects to be lost without requiring
any explicit cast.
So it is a good idea to mandate the addition of a const_cast...
Regards,
Ivan
--
http://ivan.vecerina.com
http://www.brainbench.com <> Brainbench MVP for C++
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Ralf Guest
|
Posted: Sun Oct 26, 2003 5:17 am Post subject: Re: Error C2440 when allocating array of pointers |
|
|
"Matthias Hofmann" <hofmann (AT) anvil-soft (DOT) com> schrieb im Newsbeitrag
news:bncc81$mld$1 (AT) news1 (DOT) nefonline.de...
| Quote: | Hello,
I get an error C2440 when I compile the following code on VC++ 6.0:
int main( void )
{
const int** p1 = new int*[20]; // Error: Cannot convert from 'int **
'
to 'const int ** '
const int** p2 = new const int*[20]; // Works fine.
return 0;
}
Usually it is ok to assign a pointer to a non-constant object to a pointer
to a constant object. Is this compliant with the standard and if so, why?
|
Hi,
I think, this is standard conformant. You can convert an pointer adding the
"const" specification.
int i;
int const *p = &i;
But you cannot convert pointers implicitly with two different target types.
The target type of p1 is 'const int *'. The target type of the right side is
'int *'.
Ralf
www.oop-trainer.de
www.cplusplus-kurse.de
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Siemel Naran Guest
|
Posted: Sun Oct 26, 2003 11:08 am Post subject: Re: Error C2440 when allocating array of pointers |
|
|
"Dhruv" <dhruvbird (AT) gmx (DOT) net> wrote in message
| Quote: | Try this:
typedef int* pint;
int main()
{
const pint* p1 = new int*[20];
}
|
This is the same as
int * *const p1 = new int*[20];
which is a different issue. Const protects whatever's to its left, so it
the double pointer p1 that is const.
--
+++++++++++
Siemel Naran
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
John Potter Guest
|
Posted: Sun Oct 26, 2003 7:11 pm Post subject: Re: Error C2440 when allocating array of pointers |
|
|
On 26 Oct 2003 01:15:25 -0400, "Dhruv" <dhruvbird (AT) gmx (DOT) net> wrote:
| Quote: | On Sat, 25 Oct 2003 04:33:49 -0400, Matthias Hofmann wrote:
const int** p1 = new int*[20]; // Error: Cannot convert from 'int ** '
to 'const int ** '
const int** p2 = new const int*[20]; // Works fine.
Try this:
typedef int* pint;
int main()
{
const pint* p1 = new int*[20];
}
|
That compiles because it is
int* const* p1 = new int*[20];
That is much different from what was desired. How do you plan
to make any of those uninitialized const pointers point at
anything?
int const* const* p1 = new int*[20];
That will also compile and be just as useless.
John
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
John Potter Guest
|
Posted: Sun Oct 26, 2003 7:13 pm Post subject: Re: Error C2440 when allocating array of pointers |
|
|
On 26 Oct 2003 06:08:10 -0500, "Siemel Naran"
<SiemelNaran (AT) REMOVE (DOT) att.net> wrote:
| Quote: | "Dhruv" <dhruvbird (AT) gmx (DOT) net> wrote in message
typedef int* pint;
int main()
{
const pint* p1 = new int*[20];
}
This is the same as
int * *const p1 = new int*[20];
which is a different issue. Const protects whatever's to its left, so it
the double pointer p1 that is const.
|
No, const pint* is pint const* is int*const*.
John
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Matthias Hofmann Guest
|
Posted: Sun Oct 26, 2003 7:15 pm Post subject: Re: Error C2440 when allocating array of pointers |
|
|
Ivan Vecerina <please_use_web_form (AT) ivan (DOT) vecerina.com> schrieb in im
Newsbeitrag: [email]3f9b094a (AT) news (DOT) swissonline.ch[/email]...
| Quote: | Hi Matthias,
"Matthias Hofmann" <hofmann (AT) anvil-soft (DOT) com> wrote in message
news:bncc81$mld$1 (AT) news1 (DOT) nefonline.de...
I get an error C2440 when I compile the following code on VC++ 6.0:
int main( void )
{
const int** p1 = new int*[20]; // Error: Cannot convert from 'int
**
'
to 'const int ** '
....
Usually it is ok to assign a pointer to a non-constant object to a
pointer
to a constant object. Is this compliant with the standard and if so,
why?
Yes, because of the classic problem which is decomposed below:
int* pi = 0;
int** ppi = π
const int** ppci = ppi; // illegal ... see why below <XX
const int ci = 5;
*ppci = &ci; // oho... by storing a const int* into pi,
// this effectively casts the const out
**ppi = 4; // this now modifies ci => UNDEFINED BEHAVIOR
Basically, if the <XX> statement were legal, it would allow
the constness of some objects to be lost without requiring
any explicit cast.
So it is a good idea to mandate the addition of a const_cast...
|
This sounds quite logical to me. However, what about the following case:
int i = 0;
int* p = &i;
const int* cp = &i;
++( *p ); // Modifies both *p and *cp, the latter of which is const!
This is another way to bypass the constness of an object, which is likely to
occur frequently in a program. According to the standard, is the behaviour
of this undefined as well?
Best regards,
Matthias Hofmann
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
John Potter Guest
|
Posted: Sun Oct 26, 2003 11:59 pm Post subject: Re: Error C2440 when allocating array of pointers |
|
|
On 26 Oct 2003 14:15:20 -0500, "Matthias Hofmann"
<hofmann (AT) anvil-soft (DOT) com> wrote:
| Quote: | Ivan Vecerina <please_use_web_form (AT) ivan (DOT) vecerina.com> schrieb in im
Newsbeitrag: [email]3f9b094a (AT) news (DOT) swissonline.ch[/email]...
int* pi = 0;
int** ppi = π
const int** ppci = ppi; // illegal ... see why below <XX
const int ci = 5;
*ppci = &ci; // oho... by storing a const int* into pi,
// this effectively casts the const out
**ppi = 4; // this now modifies ci => UNDEFINED BEHAVIOR
Basically, if the <XX> statement were legal, it would allow
the constness of some objects to be lost without requiring
any explicit cast.
So it is a good idea to mandate the addition of a const_cast...
This sounds quite logical to me. However, what about the following case:
int i = 0;
int* p = &i;
const int* cp = &i;
++( *p ); // Modifies both *p and *cp, the latter of which is const!
This is another way to bypass the constness of an object, which is likely to
occur frequently in a program. According to the standard, is the behaviour
of this undefined as well?
|
There is a big difference. In the first example, a non-const path to a
truely const object was obtained without a cast. In your example there
are both const and non-const paths to a non-const object. This happens
all of the time and the first is forbidden by the language.
John
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Ivan Vecerina Guest
|
Posted: Mon Oct 27, 2003 7:22 am Post subject: Re: Error C2440 when allocating array of pointers |
|
|
"Matthias Hofmann" <hofmann (AT) anvil-soft (DOT) com> wrote
| Quote: | Ivan Vecerina <please_use_web_form (AT) ivan (DOT) vecerina.com> schrieb in im
Newsbeitrag: [email]3f9b094a (AT) news (DOT) swissonline.ch[/email]...
......
This sounds quite logical to me. However, what about the following case:
int i = 0;
int* p = &i;
const int* cp = &i;
++( *p ); // Modifies both *p and *cp, the latter of which is const!
This is another way to bypass the constness of an object, which is likely
to
occur frequently in a program. According to the standard, is the behaviour
of this undefined as well?
|
This code snippet does not actually bypass the constness
of an *object*, since the object 'i' is not const.
It does however modify an object on which you hold a const
pointer (or reference), which is perfectly legal.
A const reference does not allow the direct modification of the
object it points to, but the object may still be modified by
other means.
Take for example:
void addup_twice(int& val, int const& inc)
{
val += inc; // compiler cannot optimize this as
val += inc; // a single val += 2*inc operation.
}
The output of the following statements:
int i = 1;
addup_twice( i, i );
std::cout << i << std::endl;
is well-defined and required to be 4.
Having two references to the same object or memory is called
aliasing. A C/C++ compiler is required to generate code that
behaves correctly when aliasing occurs, which does prevent
several "obvious" optimizations. ( This is why the 'restrict'
keyword has been introduced in the 99 C standard, and will
most likely be adopted by C++0x ).
[ Another example would be const volatile variables (such as
memory-mapped input ports), which cannot be modified
by code that uses them, but may have a different value
every time they are accessed. ]
Kind regards,
Ivan
--
http://ivan.vecerina.com
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Dhruv Guest
|
Posted: Tue Oct 28, 2003 2:11 am Post subject: Re: Error C2440 when allocating array of pointers |
|
|
On Sun, 26 Oct 2003 14:11:52 -0500, John Potter wrote:
| Quote: | On 26 Oct 2003 01:15:25 -0400, "Dhruv" <dhruvbird (AT) gmx (DOT) net> wrote:
On Sat, 25 Oct 2003 04:33:49 -0400, Matthias Hofmann wrote:
const int** p1 = new int*[20]; // Error: Cannot convert from 'int ** '
to 'const int ** '
const int** p2 = new const int*[20]; // Works fine.
Try this:
typedef int* pint;
int main()
{
const pint* p1 = new int*[20];
}
That compiles because it is
int* const* p1 = new int*[20];
That is much different from what was desired. How do you plan
to make any of those uninitialized const pointers point at
anything?
int const* const* p1 = new int*[20];
That will also compile and be just as useless.
|
Ok. I got confused in the typedef thing. Speaking of which, I have never
really understood it......... Like, say you have:
typedef int type;
typedef type& rtype;
No, why can't you use rtype like this:
type foo (const rtype rf)
{
return rf;
}
int main ()
{
type aaa = 5;
const rtype ra = 23;
foo (5);
}
This doesn't seem to work...
Regards,
-Dhruv.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Matthias Hofmann Guest
|
Posted: Tue Oct 28, 2003 6:39 pm Post subject: Re: Error C2440 when allocating array of pointers |
|
|
Ivan Vecerina <please_use_web_form (AT) ivan (DOT) vecerina.com> schrieb in im
Newsbeitrag: [email]3f9c966a (AT) news (DOT) swissonline.ch[/email]...
| Quote: | "Matthias Hofmann" <hofmann (AT) anvil-soft (DOT) com> wrote in message
news:bnh1i7$anv$1 (AT) news1 (DOT) nefonline.de...
Ivan Vecerina <please_use_web_form (AT) ivan (DOT) vecerina.com> schrieb in im
Newsbeitrag: [email]3f9b094a (AT) news (DOT) swissonline.ch[/email]...
.....
This sounds quite logical to me. However, what about the following
case:
int i = 0;
int* p = &i;
const int* cp = &i;
++( *p ); // Modifies both *p and *cp, the latter of which is const!
This is another way to bypass the constness of an object, which is
likely
to
occur frequently in a program. According to the standard, is the
behaviour
of this undefined as well?
This code snippet does not actually bypass the constness
of an *object*, since the object 'i' is not const.
It does however modify an object on which you hold a const
pointer (or reference), which is perfectly legal.
A const reference does not allow the direct modification of the
object it points to, but the object may still be modified by
other means.
Take for example:
void addup_twice(int& val, int const& inc)
{
val += inc; // compiler cannot optimize this as
val += inc; // a single val += 2*inc operation.
}
The output of the following statements:
int i = 1;
addup_twice( i, i );
std::cout << i << std::endl;
is well-defined and required to be 4.
Having two references to the same object or memory is called
aliasing. A C/C++ compiler is required to generate code that
behaves correctly when aliasing occurs, which does prevent
several "obvious" optimizations. ( This is why the 'restrict'
keyword has been introduced in the 99 C standard, and will
most likely be adopted by C++0x ).
[ Another example would be const volatile variables (such as
memory-mapped input ports), which cannot be modified
by code that uses them, but may have a different value
every time they are accessed. ]
|
Thank you very much for the detailed information! Could you give a brief
explanation of what the 'restrict' keyword is supposed to do? I have never
heard of it myself.
Best regards,
Matthias Hofmann
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Ben Hutchings Guest
|
Posted: Wed Oct 29, 2003 1:25 am Post subject: Re: Error C2440 when allocating array of pointers |
|
|
In article <pan.2003.10.27.02.57.46.285660 (AT) gmx (DOT) net>,
Dhruv wrote:
<snip>
| Quote: | Ok. I got confused in the typedef thing. Speaking of which,
I have never really understood it......... Like, say you
have:
typedef int type;
typedef type& rtype;
No, why can't you use rtype like this:
type foo (const rtype rf)
{
return rf;
}
int main ()
{
type aaa = 5;
const rtype ra = 23;
foo (5);
}
This doesn't seem to work...
|
Type aliases are not macros so, regardless of what a textual
substitution might produce, cv-qualifiers on a type alias (or
type parameter) that names a compound type (such as pointer-
to-T) are applied to the compound type and not to the
fundamental or user-defined type T that it is based on.
Reference types cannot be cv-qualified; such qualification
would be meaningless since references are immutable. It is
a syntax violation to put cv-qualifiers after "&" in a
declarator, but if a reference type is named using a type
alias or a type parameter then any cv-qualifiers on it are
simply ignored. (As a test, I wrote some code that does
this; VC++ 7.1 and Comeau 4.3.3 beta both accepted the code
but warned about the ignored qualifiers.)
What the code above does is:
int foo (int & /*const ignored*/ rf)
{
return rf;
}
int main ()
{
int aaa = 5;
int & /*const ignored*/ ra = 23;
foo (5);
}
Note that cv-qualifiers on function parameters aren't part
of the function's signature anyway.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|