Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > private copy constructor question

Reply
Thread Tools

private copy constructor question

 
 
David Jobet
Guest
Posts: n/a
 
      11-29-2010
Hello,

here's a simple program :

listing 1 :
---
#include <stdio.h>

class A
{
public :
A() { printf("A()\n"); }
A(bool b) { printf("A(bool)\n");}

//private :
A(const A&) { printf("A(const A &)\n"); }
private :
const A &operator =(const A &) { printf("const A &operator =(const A &);
\n"); return *this;}
};

int main(int argc, char **argv)
{
A a0;
A a3 = true;
return 1;
}
---

I compile it with g++ (4.4.3 (Ubuntu 4.4.3-4ubuntu5)) and run it. Here's the
output :
A()
A(bool)

Cool, the copy constructor is not invoked.

Now let's make a simple modification :
(uncommenting the private access modifier in listing 1 to make the copy
constructor private)

listing 2
---
#include <stdio.h>

class A
{
public :
A() { printf("A()\n"); }
A(bool b) { printf("A(bool)\n");}

private :
A(const A&) { printf("A(const A &)\n"); }
private :
const A &operator =(const A &) { printf("const A &operator =(const A &);
\n"); return *this;}
};

int main(int argc, char **argv)
{
A a0;
A a3 = true;
return 1;
}
---

Still compiling it with the same compiler. Here are the errors :
test.cpp: In function ‘int main(int, char**)’:
test.cpp:10: error: ‘A::A(const A&)’ is private
test.cpp:18: error: within this context

Not cool. Don't understand.
First listing "shows" that I'm not using the copy constructor, but in
listing 2, if I make this "not used" copy constructor private, it does not
compile ?!!

What am I missing here ?

Tx

David

PS : oh, and I'm just copmpiling it like this :
$> g++ test.cpp
then invoking the output (if it compiles) from
$> ./a.out

 
Reply With Quote
 
 
 
 
Öö Tiib
Guest
Posts: n/a
 
      11-29-2010
On Nov 29, 6:10*am, David Jobet <david.jo...@free.fr> wrote:
> Hello,
>
> here's a simple program :
>
> listing 1 :
> ---
> #include <stdio.h>
>
> class A
> {
> public :
> * A() { printf("A()\n"); }
> * A(bool b) { printf("A(bool)\n");}
>
> //private :
> * A(const A&) { printf("A(const A &)\n"); }
> private :
> * const A &operator =(const A &) { printf("const A &operator =(const A &);
> \n"); return *this;}
>
> };
>
> int main(int argc, char **argv)
> {
> * A a0;
> * A a3 = true;
> * return 1;}
>
> ---
>
> I compile it with g++ (4.4.3 (Ubuntu 4.4.3-4ubuntu5)) and run it. Here's the
> output :
> A()
> A(bool)
>
> Cool, the copy constructor is not invoked.
>
> Now let's make a simple modification :
> (uncommenting the private access modifier in listing 1 to make the copy
> constructor private)
>
> listing 2
> ---
> #include <stdio.h>
>
> class A
> {
> public :
> * A() { printf("A()\n"); }
> * A(bool b) { printf("A(bool)\n");}
>
> private :
> * A(const A&) { printf("A(const A &)\n"); }
> private :
> * const A &operator =(const A &) { printf("const A &operator =(const A &);
> \n"); return *this;}
>
> };
>
> int main(int argc, char **argv)
> {
> * A a0;
> * A a3 = true;
> * return 1;}
>
> ---
>
> Still compiling it with the same compiler. Here are the errors :
> test.cpp: In function ‘int main(int, char**)’:
> test.cpp:10: error: ‘A::A(const A&)’ is private
> test.cpp:18: error: within this context
>
> Not cool. Don't understand.
> First listing "shows" that I'm not using the copy constructor, but in
> listing 2, if I make this "not used" copy constructor private, it does not
> compile ?!!
>
> What am I missing here ?


It is about optimization. As result of the optimization copy
initialization works like direct initialization. It is OK because
compiler is allowed to optimize copy construction out when copy
initializing. Copy constructor must be still accessible. Same thing
happens with return value optimization ... copying may be optimized
out, copy constructor must be still accessible.

 
Reply With Quote
 
 
 
 
Juha Nieminen
Guest
Posts: n/a
 
      11-29-2010
David Jobet <> wrote:
> Cool, the copy constructor is not invoked.


Just because it's not being called doesn't mean it's not required, as
per the language definition. In this case, it is required (but the
compiler is allowed to skip calling it).

 
Reply With Quote
 
David Jobet
Guest
Posts: n/a
 
      11-30-2010
OK, makes sense, never thought of that as an optimization, I thought it was
in the spec and did not understand it completly obviously.
The comparison with the return value optimization helped.

Tx very much for the answer.

I have an additional question : I have been implementing the c++0x atomic
lib out of despair of finding it available on the web someplace else.
(you can find it here when the website works :
http://david.jobet.free.fr/wiclear-blog/)

The gcc "c++0x" version works fine, and I'm now trying to adapt it to make
it work with c++98.
Problem, the copy constructor is private. (as well as the assignment
operator)
So how do you suggest I make user code compiles unchanged in c++98 mode ?

For example :
std::atomic_flag af = ATOMIC_FLAG_INIT;

Where I changed the definition of ATOMIC_FLAG_INIT from "{false}" in c++0x
to just "false" in c++98.

Do you have any advice ?

David

PS : also tx to Juha Nieminen in the other thread.

Öö Tiib wrote:
> It is about optimization. As result of the optimization copy
> initialization works like direct initialization. It is OK because
> compiler is allowed to optimize copy construction out when copy
> initializing. Copy constructor must be still accessible. Same thing
> happens with return value optimization ... copying may be optimized
> out, copy constructor must be still accessible.


 
Reply With Quote
 
David Jobet
Guest
Posts: n/a
 
      11-30-2010
A direct link may help : http://david.jobet.free.fr/wiclear-
blog/images/atomic-2010-11-26.tgz

David Jobet wrote:

> OK, makes sense, never thought of that as an optimization, I thought it
> was in the spec and did not understand it completly obviously.
> The comparison with the return value optimization helped.
>
> Tx very much for the answer.
>
> I have an additional question : I have been implementing the c++0x atomic
> lib out of despair of finding it available on the web someplace else.
> (you can find it here when the website works :
> http://david.jobet.free.fr/wiclear-blog/)
>
> The gcc "c++0x" version works fine, and I'm now trying to adapt it to make
> it work with c++98.
> Problem, the copy constructor is private. (as well as the assignment
> operator)
> So how do you suggest I make user code compiles unchanged in c++98 mode ?
>
> For example :
> std::atomic_flag af = ATOMIC_FLAG_INIT;
>
> Where I changed the definition of ATOMIC_FLAG_INIT from "{false}" in c++0x
> to just "false" in c++98.
>
> Do you have any advice ?
>
> David
>
> PS : also tx to Juha Nieminen in the other thread.
>
> Öö Tiib wrote:
>> It is about optimization. As result of the optimization copy
>> initialization works like direct initialization. It is OK because
>> compiler is allowed to optimize copy construction out when copy
>> initializing. Copy constructor must be still accessible. Same thing
>> happens with return value optimization ... copying may be optimized
>> out, copy constructor must be still accessible.


 
Reply With Quote
 
Öö Tiib
Guest
Posts: n/a
 
      11-30-2010
On Nov 30, 5:28*am, David Jobet <david.jo...@free.fr> wrote:
>
> I have an additional question : I have been implementing the c++0x atomic
> lib out of despair of finding it available on the web someplace else.
> (you can find it here when the website works :http://david.jobet.free.fr/wiclear-blog/)
>
> The gcc "c++0x" version works fine, and I'm now trying to adapt it to make
> it work with c++98.
> Problem, the copy constructor is private. (as well as the assignment
> operator)
> So how do you suggest I make user code compiles unchanged in c++98 mode ?


C++0x will have std::atomic<> in it, C++98 does not contain any
support for atomic operations (or even threads).

When atomic operations are needed for C++98 or C++03 code then my
first suggestion is to use platform support.

If it needs to be portable C++98 code then simplest is perhaps to take
some library that supports atomic operations on multiple platforms.
Boehm garbage collector for example contains such libatomic_ops part
that works on lot of popular platforms.

 
Reply With Quote
 
David Jobet
Guest
Posts: n/a
 
      12-01-2010
Let me clarify :
- I don't want to use a 3rd party lib since c++0x is nearly there. I'd like
to base my code on it right now so I don't have to port my code to it when
it's available
- I could use the boost impl of the atomic lib, but the implementation is
partial and I'm not sure I agree with the impl
- I could buy the lib from Anthony Williams http://www.stdthread.co.uk/, and
I would better trust his lib than others, but I tend to prefer open source
(even if I understand the motivation to sell it)
- so instead since this lib can be entirely implemented without any help
from the compiler, I implemented it myself. It took me some time, but it was
great. I now have a good understanding of the different c++ memory models,
and this was not easy !

So since this lib can be implemented without any special support from the
compiler, making it work for c++0x or for c++98 is just a matter of
- changing "deleted" constructors/operators in c++0x to private signature in
c++98
- changing "default" constructor impl in c++0x to inline impl in c++98
- ignoring the constexpr declarator
- ...

The only thing which makes me choke right now is the deleted copy
constructor and the deleted assignment operator.

Because of them, I cannot write easily
std::atomic_flag af = ATOMIC_FLAG_INIT;

According to the spec, the macro ATOMIC_FLAG_INIT expands to "something"
allowing to initialize the atomic_flag to a clear state.

In c++0x it just expands to {false}, and it works thanks to the support for
initializer list.
This does not work in c++98, so I tried to change it to "false", hoping it
would go through the constructor, but then I found out the private copy
constructor forbids the initialization.

So I was just hoping to get an idea from you about getting around that
problem.

Just found it while typing this message : instead of declaring the inner
value private, I can make it public, then I can use the {false}
initialization while still forbiding copying...

I'm breaking a little bit the encapsulation, but the API remains mostly
unchanged.

Tx

David


Öö Tiib wrote:

> On Nov 30, 5:28 am, David Jobet <david.jo...@free.fr> wrote:
>>
>> I have an additional question : I have been implementing the c++0x atomic
>> lib out of despair of finding it available on the web someplace else.
>> (you can find it here when the website works
>> :http://david.jobet.free.fr/wiclear-blog/)
>>
>> The gcc "c++0x" version works fine, and I'm now trying to adapt it to
>> make it work with c++98.
>> Problem, the copy constructor is private. (as well as the assignment
>> operator)
>> So how do you suggest I make user code compiles unchanged in c++98 mode ?

>
> C++0x will have std::atomic<> in it, C++98 does not contain any
> support for atomic operations (or even threads).
>
> When atomic operations are needed for C++98 or C++03 code then my
> first suggestion is to use platform support.
>
> If it needs to be portable C++98 code then simplest is perhaps to take
> some library that supports atomic operations on multiple platforms.
> Boehm garbage collector for example contains such libatomic_ops part
> that works on lot of popular platforms.


 
Reply With Quote
 
David Jobet
Guest
Posts: n/a
 
      12-01-2010
OK, forget about that solution, this works only with an empty class...

David Jobet wrote:

> Let me clarify :
> - I don't want to use a 3rd party lib since c++0x is nearly there. I'd
> like to base my code on it right now so I don't have to port my code to it
> when it's available
> - I could use the boost impl of the atomic lib, but the implementation is
> partial and I'm not sure I agree with the impl
> - I could buy the lib from Anthony Williams http://www.stdthread.co.uk/,
> and I would better trust his lib than others, but I tend to prefer open
> source (even if I understand the motivation to sell it)
> - so instead since this lib can be entirely implemented without any help
> from the compiler, I implemented it myself. It took me some time, but it
> was great. I now have a good understanding of the different c++ memory
> models, and this was not easy !
>
> So since this lib can be implemented without any special support from the
> compiler, making it work for c++0x or for c++98 is just a matter of
> - changing "deleted" constructors/operators in c++0x to private signature
> in c++98
> - changing "default" constructor impl in c++0x to inline impl in c++98
> - ignoring the constexpr declarator
> - ...
>
> The only thing which makes me choke right now is the deleted copy
> constructor and the deleted assignment operator.
>
> Because of them, I cannot write easily
> std::atomic_flag af = ATOMIC_FLAG_INIT;
>
> According to the spec, the macro ATOMIC_FLAG_INIT expands to "something"
> allowing to initialize the atomic_flag to a clear state.
>
> In c++0x it just expands to {false}, and it works thanks to the support
> for initializer list.
> This does not work in c++98, so I tried to change it to "false", hoping it
> would go through the constructor, but then I found out the private copy
> constructor forbids the initialization.
>
> So I was just hoping to get an idea from you about getting around that
> problem.
>
> Just found it while typing this message : instead of declaring the inner
> value private, I can make it public, then I can use the {false}
> initialization while still forbiding copying...
>
> I'm breaking a little bit the encapsulation, but the API remains mostly
> unchanged.
>
> Tx
>
> David
>
>
> Öö Tiib wrote:
>
>> On Nov 30, 5:28 am, David Jobet <david.jo...@free.fr> wrote:
>>>
>>> I have an additional question : I have been implementing the c++0x
>>> atomic lib out of despair of finding it available on the web someplace
>>> else. (you can find it here when the website works
>>> :http://david.jobet.free.fr/wiclear-blog/)
>>>
>>> The gcc "c++0x" version works fine, and I'm now trying to adapt it to
>>> make it work with c++98.
>>> Problem, the copy constructor is private. (as well as the assignment
>>> operator)
>>> So how do you suggest I make user code compiles unchanged in c++98 mode
>>> ?

>>
>> C++0x will have std::atomic<> in it, C++98 does not contain any
>> support for atomic operations (or even threads).
>>
>> When atomic operations are needed for C++98 or C++03 code then my
>> first suggestion is to use platform support.
>>
>> If it needs to be portable C++98 code then simplest is perhaps to take
>> some library that supports atomic operations on multiple platforms.
>> Boehm garbage collector for example contains such libatomic_ops part
>> that works on lot of popular platforms.


 
Reply With Quote
 
Öö Tiib
Guest
Posts: n/a
 
      12-01-2010
On Dec 1, 5:43*am, David Jobet <david.jo...@free.fr> wrote:
> Let me clarify :
> - I don't want to use a 3rd party lib since c++0x is nearly there. I'd like
> to base my code on it right now so I don't have to port my code to it when
> it's available
> - I could use the boost impl of the atomic lib, but the implementation is
> partial and I'm not sure I agree with the impl
> - I could buy the lib from Anthony Williamshttp://www.stdthread.co.uk/, and
> I would better trust his lib than others, but I tend to prefer open source
> (even if I understand the motivation to sell it)
> - so instead since this lib can be entirely implemented without any help
> from the compiler, I implemented it myself. It took me some time, but it was
> great. I now have a good understanding of the different c++ memory models,
> and this was not easy !
>
> So since this lib can be implemented without any special support from the
> compiler, making it work for c++0x or for c++98 is just a matter of
> - changing "deleted" constructors/operators in c++0x to private signature in
> c++98
> - changing "default" constructor impl in c++0x to inline impl in c++98
> - ignoring the constexpr declarator
> - ...
>
> The only thing which makes me choke right now is the deleted copy
> constructor and the deleted assignment operator.
>
> Because of them, I cannot write easily
> std::atomic_flag af = ATOMIC_FLAG_INIT;


You can not copy initialize without public copy constructor. Perhaps
remove the declaration of copy constructor under c++98 whatsoever. It
makes your atomic_flag copyable ... but if you don't ... no harm made.
 
Reply With Quote
 
David Jobet
Guest
Posts: n/a
 
      12-02-2010
Yep, tried a lot of trick to see if I could somehow bypass it, and came up
with the same conclusion...

Tx

David

Öö Tiib wrote:

> You can not copy initialize without public copy constructor. Perhaps
> remove the declaration of copy constructor under c++98 whatsoever. It
> makes your atomic_flag copyable ... but if you don't ... no harm made.


 
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
template copy constructor vs normal copy constructor cinsk C++ 35 10-10-2010 11:14 PM
A constructor calling another constructor (default constructor)? Generic Usenet Account C++ 10 11-28-2007 04:12 AM
Initialising private base members in copy constructor Fraser Ross C++ 7 08-07-2007 07:55 AM
Private constructor,Static constructor plmanikandan@gmail.com C++ 4 03-03-2006 08:01 AM
C++ list and private copy constructor Jan C++ 7 12-06-2005 11:15 AM



Advertisments