Q: wrong const data type in constructor

C

Claudius

Hello,

in the following example, is it correct that the compiler sets the
'this'-pointer to type (const A *) in both calls of the copy-
constructor? (I compiled it with g++-4.3.4)
I had expected (A *).

class A {
public:
A( A & a ) {
int i = 2;
}

A() {}

int i;
};

int main( void ) {

A a;
A b( a ); //this = const A *, ???
const A c( b ); //this = const A *, ok

return 1;
}

So it is not possible to recognize within the copy constructor whether
a const object is to be created or not.
 
S

Saeed Amrollahi

Hello,

in the following example, is it correct that the compiler sets the
'this'-pointer to type (const A *) in both calls of the copy-
constructor?  (I compiled it with g++-4.3.4)
I had expected (A *).

class A {
public:
    A( A & a ) {
        int i = 2;
    }

    A() {}

    int i;

};

int main( void ) {

    A a;
    A b( a );           //this = const A *, ???
    const A c( b );     //this = const A *, ok

    return 1;

}

So it is not possible to recognize within the copy constructor whether
a const object is to be created or not.

Hi

The type of this pointer for class X is X* inside non-static non-
const
member function and inside const member function, it will be const X*.
this pointer is used about calling const/non-const member functions

class A {
// ...
public:
int Get() const { return i; }
void Set(int ii) /* non-const */ { i = ii; }
};

A a;
const ca;
a.Get(); // OK
a.Set(1); // OK

ca.Get(); // OK
ca.Set(2); // error

I think for const object, the this is pointer to const data,
but for non-const object it depends to the member function.

Regards,
-- Saeed Amrollhi
 
S

Salt_Peter

Hello,

in the following example, is it correct that the compiler sets the
'this'-pointer to type (const A *) in both calls of the copy-
constructor?  (I compiled it with g++-4.3.4)
I had expected (A *).

class A {
public:
    A( A & a ) {
        int i = 2;
    }

    A() {}

    int i;

};

int main( void ) {

    A a;
    A b( a );           //this = const A *, ???
    const A c( b );     //this = const A *, ok

    return 1;

}

So it is not possible to recognize within the copy constructor whether
a const object is to be created or not.

You are constructing objects from scratch.
Whether these are const or not is irrelevant.
What you are seeing is compiler optimization.

use initialization lists.
Its one of the cornerstones of C++.
Also, never ever leave a member uninitialized.
That, in effect, is the only issue you need to pay attention-to about
const objects.

class A
{
const int i;
public:
A() : i(1) { }
A( const A& copy ) : i(copy.i + 1) { }
};

Incidentally, if you where to use your A( A & a ) copy-ctor in the
following statement it would fail:
A a = A(); // tries to copy a temporary object
 
P

Paul Bibbings

Claudius said:
Hello,

in the following example, is it correct that the compiler sets the
'this'-pointer to type (const A *) in both calls of the copy-
constructor? (I compiled it with g++-4.3.4)
I had expected (A *).

class A {
public:
A( A & a ) {
int i = 2;
}

A() {}

int i;
};

int main( void ) {

A a;
A b( a ); //this = const A *, ???
const A c( b ); //this = const A *, ok

return 1;
}

So it is not possible to recognize within the copy constructor whether
a const object is to be created or not.

Can I ask, how exactly you are determining that the this pointer is set
to const A * in both copy-ctor calls? I ask this because I'm getting A
* const in both instances.

10:58:34 Paul Bibbings@JIJOU
/cygdrive/d/CPPProjects/CLCPP $gcc -O0 -gdwarf-2 -g3 -c
const_this.cpp

10:58:38 Paul Bibbings@JIJOU
/cygdrive/d/CPPProjects/CLCPP $g++ -Wl,--enable-auto-import -static
-o const_this const_this.o

10:58:47 Paul Bibbings@JIJOU
/cygdrive/d/CPPProjects/CLCPP $gdb ./const_this
GNU gdb (GDB) 7.0.50.20100128-cvs
...
Reading symbols from
/cygdrive/d/CPPProjects/CLCPP/const_this...done.
(gdb) break const_this.cpp:15
Breakpoint 1 at 0x4010fa: file const_this.cpp, line 15.
(gdb) break const_this.cpp:16
Breakpoint 2 at 0x40110e: file const_this.cpp, line 16.
(gdb) run
Starting program: /cygdrive/d/CPPProjects/CLCPP/const_this
[New Thread 7204.0x1c28]
[New Thread 7204.0x1c2c]

Breakpoint 1, main () at const_this.cpp:15
15 A b( a ); // this = const A *, ???
(gdb) step
A (this=0x22ccf8, a=...) at const_this.cpp:4
4 int i = 1;
(gdb) print this
$1 = (A * const) 0x22ccf8
(gdb) continue
Continuing.

Breakpoint 2, main () at const_this.cpp:16
16 const A c( b ); // this = const A *, ok
(gdb) step
A (this=0x22ccf4, a=...) at const_this.cpp:4
4 int i = 1;
(gdb) print this
$2 = (A * const) 0x22ccf4
(gdb)

It is only if I add something like a const member function that I get a
pointer to const, such as:

Breakpoint 1, main () at const_this.cpp:19
19 a.get();
(gdb) step
A::get (this=0x22ccfc) at const_this.cpp:9
9 int get() const { return i; }
(gdb) print this
$1 = (const A * const) 0x22ccfc
(gdb)

Regards

Paul Bibbings
 
C

Claudius

You are constructing objects from scratch.
Whether these are const or not is irrelevant.
What you are seeing is compiler optimization.

use initialization lists.
Its one of the cornerstones of C++.
Also, never ever leave a member uninitialized.
That, in effect, is the only issue you need to pay attention-to about
const objects.

class A
{
    const int i;
  public:
    A() : i(1) { }
    A( const A& copy ) : i(copy.i + 1) { }

};

Incidentally, if you where to use your A( A & a ) copy-ctor in the
following statement it would fail:
A a = A(); // tries to copy a temporary object

Is it possible to disable the corresponding compiler optimization so
that within the copy-ctor a decision is possible whether a const or
non-const object is to be created?
 
C

Claudius

Claudius said:
in the following example, is it correct that the compiler sets the
'this'-pointer to type (const A *) in both calls of the copy-
constructor?  (I compiled it with g++-4.3.4)
I had expected (A *).
class A {
public:
    A( A & a ) {
        int i = 2;
    }
    A() {}
    int i;
};
int main( void ) {
    A a;
    A b( a );           //this = const A *, ???
    const A c( b );     //this = const A *, ok
    return 1;
}
So it is not possible to recognize within the copy constructor whether
a const object is to be created or not.

Can I ask, how exactly you are determining that the this pointer is set
to const A * in both copy-ctor calls?  I ask this because I'm getting A
* const in both instances.

   10:58:34 Paul Bibbings@JIJOU
   /cygdrive/d/CPPProjects/CLCPP $gcc -O0 -gdwarf-2 -g3 -c
      const_this.cpp

   10:58:38 Paul Bibbings@JIJOU
   /cygdrive/d/CPPProjects/CLCPP $g++ -Wl,--enable-auto-import -static
      -o const_this const_this.o

   10:58:47 Paul Bibbings@JIJOU
   /cygdrive/d/CPPProjects/CLCPP $gdb ./const_this
   GNU gdb (GDB) 7.0.50.20100128-cvs
   ...
   Reading symbols from
      /cygdrive/d/CPPProjects/CLCPP/const_this...done.
   (gdb) break const_this.cpp:15
   Breakpoint 1 at 0x4010fa: file const_this.cpp, line 15.
   (gdb) break const_this.cpp:16
   Breakpoint 2 at 0x40110e: file const_this.cpp, line 16.
   (gdb) run
   Starting program: /cygdrive/d/CPPProjects/CLCPP/const_this
   [New Thread 7204.0x1c28]
   [New Thread 7204.0x1c2c]

   Breakpoint 1, main () at const_this.cpp:15
   15         A b( a );           // this = const A *, ???
   (gdb) step
   A (this=0x22ccf8, a=...) at const_this.cpp:4
   4             int i = 1;
   (gdb) print this
   $1 = (A * const) 0x22ccf8
   (gdb) continue
   Continuing.

   Breakpoint 2, main () at const_this.cpp:16
   16         const A c( b );     // this = const A *, ok
   (gdb) step
   A (this=0x22ccf4, a=...) at const_this.cpp:4
   4             int i = 1;
   (gdb) print this
   $2 = (A * const) 0x22ccf4
   (gdb)

It is only if I add something like a const member function that I get a
pointer to const, such as:

   Breakpoint 1, main () at const_this.cpp:19
   19         a.get();
   (gdb) step
   A::get (this=0x22ccfc) at const_this.cpp:9
   9          int get() const { return i; }
   (gdb) print this
   $1 = (const A * const) 0x22ccfc
   (gdb)

Regards

Paul Bibbings

You are right, this is a 'A * const'.
I started the small test program within the insight debugger (gdb-
based).
In the other calls however, it is always 'A * const' even if a non-
const object is to be created.
 
V

Victor Bazarov

[..]
So it is not possible to recognize within the copy constructor whether
a const object is to be created or not.

Inside any constructor it's impossible to recognize. Until the moment
the constructor's body finishes executing, the object is effectively
under construction and cannot be considered const. IIRC, of course.

V
 
P

Paul Bibbings

You are right, this is a 'A * const'.
I started the small test program within the insight debugger (gdb-
based).
In the other calls however, it is always 'A * const' even if a non-
const object is to be created.

What I can't understand, though, is *why* the gcc/gdb combination is
reporting the top-level const when, as the Standard says:

[expr.prim] §5.1/3
"The keyword this names a pointer to the object for which a nonstatic
member function (9.3.2) is invoked. [...] The type of the expression
is a pointer to the function's class (9.3.2), possibly with
cv-qualifiers on the class type. The expression is an rvalue."

and this is clarified in §9.3.2, in pretty much the same terms as Saeed
used:

[class.this] §9.3.2/1
"In the body of a nonstatic (9.3) member function, the keyword this
is a non-lvalue expression whose value is the address of the object
for which the function is called. The type of this in a member
function of class X is X*. If the member function is declared const,
the type of this is const X*..."

So, from the above, I would have expected A* and const A* where we found
A* const and const A* const.

Obviously this is a `special' kind of pointer in some sense, and can't
be assigned to in any circumstance in user code, as far as I am aware.
But it doesn't appear that it is const either.

Curious!

Regards

Paul Bibbings
 
K

Kai-Uwe Bux

Victor said:
[..]
So it is not possible to recognize within the copy constructor whether
a const object is to be created or not.

Inside any constructor it's impossible to recognize. Until the moment
the constructor's body finishes executing, the object is effectively
under construction and cannot be considered const. IIRC, of course.

You recall correctly. It's in [12.1/4].

BTW, the same is true for destructors [12.4/2].


Best

Kai-Uwe Bux
 
B

Bo Persson

Claudius said:
Is it possible to disable the corresponding compiler optimization so
that within the copy-ctor a decision is possible whether a const or
non-const object is to be created?

No. Why should creating an object be different for these cases?


Bo Persson
 
C

Claudius

No. Why should creating an object be different for these cases?

Bo Persson

In the copy-ctor I'd like to reference the data structures of the
other object instead of copying them.
Then, with reference counting pointers it is possible to use the copy-
ctor to return local objects with data structures on the heap by value
as it were 'by reference'.

BUT this breaks const-correctness if it is not possible to treat it
correctly. For an example see the array class in the blitz library.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top