Topic: Copy constructor invoked where RHS is itself?


Author: Mark Radford <usenet-news@twonine.demon.co.uk>
Date: Tue, 25 Sep 2001 17:35:14 GMT
Raw View
In article <d6651fb6.0109210244.55805258@posting.google.com>, James
Kanze <kanze@gabi-soft.de> writes
>Mark Radford <twonine@twonine.demon.co.uk> wrote in message
>news:<3jyGXRAGvcq7EwhM@twonine.demon.co.uk>...
>> In article <3ba87e8e$0$225$ed9e5944@reading.news.pipex.net>, Stephen
>> Howe <SPAMstephen.howeGUARD@tnsofres.com> writes
[...]
>> >  vector<string> v = v;
[...]
>> AFAIK this is a C legacy.
>
>It's true that similar code is legal in C.  But in the case of C++,
>there are actually cases where it makes sense.

Yes, I've heard this before but have never seen an explanation; please,
could you post an example of how it can be taken advantage of sensibly
(thanks).

[...]

>> vector<string> v(v); // Error
>
>> Using parentheses you're safe from this - v will not be in scope
>> until the semicolon.
>
>Not according to the standard.  When the symbol becomes visible isn't
>(directly) dependant on any particular character.  According to
>3.3.1/1, "The point of declaration for a name is immediately after its
>complete declarator (clause 8) and before its initializer (if any),
>except as noted below."  In the above, the (v) is an initializor, and
>not part of the declarator.  (See also the grammar in chapter 8.)  The
>above is just as legal as v = v.

Oops yes. Thanks for the correction.
 ---
 Mark Radford (Opinions are my own unless explicitly stated otherwise)
 twoNine Computer Services Limited - C++, Design, Development, Consultancy
 http://www.twonine.demon.co.uk/computing.htm
 Find out about ACCU at www.accu.org

---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: Andre@incognito.com (Andre Kostur)
Date: 25 Sep 2001 19:56:46 GMT
Raw View
"Stephen Howe" <NOSPAMsjhowe@dial.pipex.com> wrote in
<3baa802a$0$8512$cc9e4d1f@news.dial.pipex.com>:

>
>
>"Jeff Greif" <jgreif@spam-me-not.alumni.princeton.edu> wrote in message
>news:8l4q7.29946$Ed3.5891976@typhoon.we.rr.com...
>>
>> I would *guess* it's legal.  Many assignment operators have an
>> identity check (and punting of the rest of the operation when it's
>> satisfied.) If your implementation blows up, it may be missing this
>> check and the vendor would have a bug to fix if the assignment is
>> legal (even if it is pointless).
>
>Jeff:
>
>That isn't the assignment operator, that is the copy constructor.
>
>
>Everyone:
>
>Thanks. Why doesn't the standard make it undefined behavour? It seems a

It already is undefined behaviour.  You're accessing an object before it's
had a chance to be constructed.



      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ 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.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]






Author: Michiel Salters<Michiel.Salters@cmg.nl>
Date: Wed, 26 Sep 2001 14:43:30 GMT
Raw View
In article <lnQC2JAX7Is7EwS6@twonine.demon.co.uk>, Mark Radford says...
>
>In article <d6651fb6.0109210244.55805258@posting.google.com>, James
>Kanze <kanze@gabi-soft.de> writes
>>Mark Radford <twonine@twonine.demon.co.uk> wrote in message
>>news:<3jyGXRAGvcq7EwhM@twonine.demon.co.uk>...
>>> In article <3ba87e8e$0$225$ed9e5944@reading.news.pipex.net>, Stephen
>>> Howe <SPAMstephen.howeGUARD@tnsofres.com> writes
>[...]
>>> >  vector<string> v = v;
>[...]
>>> AFAIK this is a C legacy.
>>
>>It's true that similar code is legal in C.  But in the case of C++,
>>there are actually cases where it makes sense.

class C
{
C* someC;
public:
C( C* someC_ ) : someC (someC_) { }
}

C a(0) // legal, a.someC==0
C b(&a) // legal, b.someC==&a
C c(&c) // legal, c.someC==&c

E.g. for a circular buffer, to start with a single element which
means that single element has to point to itself.

HTH,

--
Michiel Salters
Consultant Technical Software Engineering
CMG Trade, Transport & Industry
Michiel.Salters@cmg.nl

---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: Wed, 26 Sep 2001 16:10:50 GMT
Raw View
In article <1wfs7.5487$ev2.9077@www.newsranger.com>, Michiel Salters
<Michiel.Salters@cmg.nl> writes
>class C
>{
>C* someC;
>public:
>C( C* someC_ ) : someC (someC_) { }
>}
>
>C a(0) // legal, a.someC==0
>C b(&a) // legal, b.someC==&a
>C c(&c) // legal, c.someC==&c
>
>E.g. for a circular buffer, to start with a single element which
>means that single element has to point to itself.

Notice that you are passing a pointer to C, the problem case passes a
reference. The problem that I have is that the idiom hijacks the copy
ctor to do something that is not copying.

Francis Glassborow
I offer my sympathy and prayers to all those who are suffering
as a result of the events of September 11 2001.

---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: Anthony Yuen <yuen@cs.dal.ca>
Date: 23 Sep 2001 16:24:02 GMT
Raw View
In article <3ba87e8e$0$225$ed9e5944@reading.news.pipex.net> you wrote:
>
> Is this valid according to the standard:
>
>>>>>>>>>>>>>>>>>>>
> #include <iostream>
> #include <string>
> #include <vector>
>
> using namespace std;
>
> int main() {
>   string         s = s;
>   vector<string> v = v;
>   v.push_back( s);
>   cout << "s = " << v[ 0] << endl;
>
>   return 0;
> }
>>>>>>>>>>>>>>>>>>>
>
> It gets past my compiler with no diagnostics and promptly blows up.
> I find this disturbing if it turns out that it is valid.
>

 There is nothing wrong with your program as far as the syntax
is concerned.  Your program is grammatically correct.  However, when your
program is run, I suspect that it gets into an infinite recursion trying
to construct s on itself.

 Anything can happen... since "Garbage In, Garbage Out".  The input
is meaningless, so the output is meaningless as well.  What did you
expect to happen?

 As we all know, C/C++ gives the programmer enough rope to hang
himself.  Should he choose to do it (as in the case here), the compiler
will happily comply.



      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ 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.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]






Author: allan_w@my-dejanews.com (Allan W)
Date: 23 Sep 2001 16:24:03 GMT
Raw View
"Jeff Greif" <jgreif@spam-me-not.alumni.princeton.edu> wrote in message
news:<8l4q7.29946$Ed3.5891976@typhoon.we.rr.com>...
> I would *guess* it's legal.  Many assignment operators have an identity
> check (and punting of the rest of the operation when it's satisfied.)
> If your implementation blows up, it may be missing this check and the
> vendor would have a bug to fix if the assignment is legal (even if it is
> pointless).

The code below doesn't invoke the assignment operator. It invokes the
copy constructor.

> "Stephen Howe" <SPAMstephen.howeGUARD@tnsofres.com> wrote in message
> news:3ba87e8e$0$225$ed9e5944@reading.news.pipex.net...
> >
> > Is this valid according to the standard:
> >
> > >>>>>>>>>>>>>>>>>>
> > #include <iostream>
> > #include <string>
> > #include <vector>
> >
> > using namespace std;
> >
> > int main() {
> >   string         s = s;
> >   vector<string> v = v;
> >   v.push_back( s);
> >   cout << "s = " << v[ 0] << endl;
> >
> >   return 0;
> > }

In your definition of s you refer to the current value of s. It
seems to me that the C++ compiler calls string's copy
constructor, with the right-hand side a reference to the same
object that's being constructed. And then the same thing happens
for the vector.

There's a common convention that states that operator= code which
isn't exception safe might also need a guard against self-assignment.
That's because code like this:
    foo &operator=(foo&rhs) {
        delete array_of_bar;
        array_of_bar = new bar[arraysize = rhs.arraysize];
        for (int i=0; i<arraysize; ++i)
           array_of_bar[i]=rhs.array_of_bar[i];
        return *this;
    }
fails miserably if a foo is assigned to itself, because the
first delete statement destroys the data you're about to copy.
That convention says it ought to be written like this instead:
    foo &operator=(foo&rhs) {
        if (this != &rhs) {    // <-- The guard
            delete array_of_bar;
            array_of_bar = new bar[arraysize = rhs.arraysize];
            for (int i=0; i<arraysize; ++i)
               array_of_bar[i]=rhs.array_of_bar[i];
        }
        return *this;
    }
The reason that I bring this up is, that same convention says
there's no need to have this type of guard for copy constructors,
because construction as copy of self is meaningless.

And yet, here you've provided evidence to the contrary.

As for weather it ought to be legal:
I know that the rules about scope allow the name to be recognized
the instant it's been parsed. I'm not going to look it up right this
second, but if I remember correctly, the reason for this was to
allow definitions such as this:

    struct LinkedList {
        LinkedList(LinkedList*prev=0, LinkedList*next=0);
        //...
    };
    LinkedList root(&root);

Since we want these constructs to continue to be legal, your
example has to be legal as well. But perhaps we could convince
compiler vendors to issue a warning. After all, string's copy
constructor should not be given an uninitialized argument!



      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ 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.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]






Author: James Dennett <jdennett@acm.org>
Date: 23 Sep 2001 16:24:02 GMT
Raw View
Bob Bell wrote:
> plain; charset=ISO-8859-1
> Content-Transfer-Encoding: 8bit
> X-Trace: posting.google.com 1000933969 17891 127.0.0.1 (19 Sep 2001 21:12:49
> GMT)
> X-Complaints-To: groups-abuse@google.com
> NNTP-Posting-Date: 19 Sep 2001 21:12:49 GMT
> Content-Length: 169
> ReSent-Date: Wed, 19 Sep 2001 16:08:07 -0700 (PDT)
> ReSent-From: Steve Clamage <clamage@eng.sun.com>
> ReSent-To:  <c++-submit@netlab.cs.rpi.edu>
> ReSent-Subject: Re: Copy constructor invoked where RHS is itself?
> ReSent-Message-ID: <Pine.SOL.4.33.0109191608070.2176@taumet>
>
>>It gets past my compiler with no diagnostics and promptly blows up.
>>I find this disturbing if it turns out that it is valid.
>>
>
> It is both valid and disturbing.

No, it's not valid.  It's syntactically valid, but accesses
an object before it is initialized -- there's no guarantee
given by the Standard that you can self-initialize a vector,
and indeed copying with this rare error isn't something
which should normally be checked at runtime (though paranoid
vendors could assert(this != &other) for debug builds).

But yes, it's a touch disturbing.

-- James Dennett



      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ 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.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]






Author: "Louis Lavery" <Louis@DevilsChimney.co.uk>
Date: 23 Sep 2001 16:24:06 GMT
Raw View

Ron Hunsinger wrote in message
<200920010351147683%hunsinger@mac.com>...
>


[snip examples]

>These are admittedly not particularly compelling examples. Maybe
>someone else can come up with some better ones.
>
>-Ron Hunsinger


Maybe...

class X
{
public:
    X() : pX_(this) {}

    X(X& x) : pX_(this)
    {
        if ( this != &x )
        {
            X *const pX = x.pX_;

            x.pX_ = pX_;

            pX_ = pX;
        }
    }

    X& operator=(X& x)
    {
        if ( this != &x )
        {
            X *const pX = x.pX_;

            x.pX_ = pX_;

            pX_ = pX;
        }

        return *this;
    }

    .
    .
private:
    X * pX_;
};

int main()
{
    X x = x;

    return 0;
}

..?

BTW is this a counter example to Herb Sutter's assertion
"checking for self-assignment in a constructor doesn't
make sense" ? (see EC++ Item 38: Postscript #1).

Regards,

Louis.















      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ 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.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]






Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: 23 Sep 2001 16:24:04 GMT
Raw View
In article <200920010351147683%hunsinger@mac.com>, Ron Hunsinger
<hunsinger@mac.com> writes
>These are admittedly not particularly compelling examples. Maybe
>someone else can come up with some better ones.

Basically it was the existence of such examples that dissuaded the
Standards Committees from changing the language to make such
declarations ill-formed.  (I know it was considered because I proposed
such a change - though possibly only informally)


Francis Glassborow
I offer my sympathy and prayers to all those who are suffering
as a result of the events of September 11 2001.



      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ 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.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]






Author: kanze@gabi-soft.de (James Kanze)
Date: 23 Sep 2001 16:24:05 GMT
Raw View

"Jeff Greif" <jgreif@spam-me-not.alumni.princeton.edu> wrote in
message news:<8l4q7.29946$Ed3.5891976@typhoon.we.rr.com>...
> "Stephen Howe" <SPAMstephen.howeGUARD@tnsofres.com> wrote in message
> news:3ba87e8e$0$225$ed9e5944@reading.news.pipex.net...

> > Is this valid according to the standard:

> > >>>>>>>>>>>>>>>>>>
> > #include <iostream>
> > #include <string>
> > #include <vector>

> > using namespace std;

> > int main() {
> >   string         s = s;
> >   vector<string> v = v;
> >   v.push_back( s);
> >   cout << "s = " << v[ 0] << endl;

> >   return 0;
> > }

    [Quoted text belongs *before* the comments on it.]

> I would *guess* it's legal.  Many assignment operators have an
> identity check (and punting of the rest of the operation when it's
> satisfied.)  If your implementation blows up, it may be missing this
> check and the vendor would have a bug to fix if the assignment is
> legal (even if it is pointless).

There's no assignment in his code, so any comments concerning the
possible implementation of the assignment operator are irrelevant.  (I
might add that it is generally considered symptomatic of a problem if
the assignment operator requires a test for self assignment.)

--
James Kanze                                   mailto:kanze@gabi-soft.de
Beratung in objektorientierer Datenverarbeitung --
                             -- Conseils en informatique oriente objet
Ziegelhttenweg 17a, 60598 Frankfurt, Germany, Tl.: +49 (0)69 19 86 27



      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ 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.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]






Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: 23 Sep 2001 16:24:04 GMT
Raw View
In article <3BA8DF19.D750A25F@data-transit.com>, Nicholas Leippe
<nick@data-transit.com> writes
>Be glad it's obvious in this case--some classes may not actually
>cause directly noticeable problems, depending on what their member
>data is.  I can't think of why someone would need to try this
>anyways--it doesn't have any conceptual merit, which is probably why
>the compiler writers didn't bother to add a test for this to issue a
>warning.

typedef vector::iterator iter;
for(iter i = v.begin(); i != v.end(); ++i){
   for(iter i = i; i != v.end(); ++i) {


Is a possible way that a naive programmer might get caught by this trap.



Francis Glassborow
I offer my sympathy and prayers to all those who are suffering
as a result of the events of September 11 2001.



      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ 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.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]






Author: "Stephen Howe" <NOSPAMsjhowe@dial.pipex.com>
Date: 23 Sep 2001 16:24:03 GMT
Raw View

"Jeff Greif" <jgreif@spam-me-not.alumni.princeton.edu> wrote in message
news:8l4q7.29946$Ed3.5891976@typhoon.we.rr.com...
>
> I would *guess* it's legal.  Many assignment operators have an identity
> check (and punting of the rest of the operation when it's satisfied.)
> If your implementation blows up, it may be missing this check and the
> vendor would have a bug to fix if the assignment is legal (even if it is
> pointless).

Jeff:

That isn't the assignment operator, that is the copy constructor.


Everyone:

Thanks. Why doesn't the standard make it undefined behavour? It seems a
perfect candidate for a DR. I shudder to think what happens when the
destructor kicks in. Perhaps self-construction should be checked for in the
copy constructor and simply throw or set a flag and return.

Stephen Howe






      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ 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.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]






Author: kanze@gabi-soft.de (James Kanze)
Date: 23 Sep 2001 16:24:05 GMT
Raw View
Ron Hunsinger <hunsinger@mac.com> wrote in message
news:<200920010351147683%hunsinger@mac.com>...

> It is disturbing, and it is valid. The standard even mentions this
> (admittedly bizarre) case:

>     3.3.1/1 [basic.scope.pdecl]
>         The point of declaration for a name is immediately after its
>         complete declarator (clause 8) and before its initializer
>         (if any), except as noted below. [Example:

>             int x = 12;
>             { int x = x; }

>         Here the second x is initialized with its own (indeterminate)
>         value. ]

> I'm guessing that the reason for allowing an object to participate
> in its own initialization is to allow initializations like the
> following:

>     struct node {
>         node *next;
>         node *prev;
>         int value; }

>     node empty = { &empty, &empty, 0 };

    [...]
> where the initializer is computable (using sizeof or operator& on
> the object or its subobject) even before the object has been
> constructed.

Correct.  In the case of C++, of course, you don't even need an
operator.  The object can be bound to a reference, and as long as it
isn't used until initialization is finished, the use is valid.

> These are admittedly not particularly compelling examples.

The one with node is a frequent pattern, and as such, fairly
compeling, at least in C.  In C++, I would prefer giving the object a
constructor.  And a default constructor could be used to initialize
both pointers to this.

--
James Kanze                                   mailto:kanze@gabi-soft.de
Beratung in objektorientierer Datenverarbeitung --
                             -- Conseils en informatique oriente objet
Ziegelhttenweg 17a, 60598 Frankfurt, Germany, Tl.: +49 (0)69 19 86 27



      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ 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.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]






Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: 23 Sep 2001 16:24:04 GMT
Raw View
In article <8l4q7.29946$Ed3.5891976@typhoon.we.rr.com>, Jeff Greif
<jgreif@spam-me-not.alumni.princeton.edu> writes
>I would *guess* it's legal.  Many assignment operators have an identity
>check (and punting of the rest of the operation when it's satisfied.)
>If your implementation blows up, it may be missing this check and the
>vendor would have a bug to fix if the assignment is legal (even if it is
>pointless).

But there are no assignment operators in that code just two calls to
copy ctors. The problem is that the copy ctor is called on objects that
have not yet been constructed.

mytype mt = mt;

is exactly equivalent to:

mytype mt(mt);



Francis Glassborow
I offer my sympathy and prayers to all those who are suffering
as a result of the events of September 11 2001.



      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ 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.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]






Author: "Bruce G. Stewart" <Bruce.G.Stewart@worldnet.att.net>
Date: 25 Sep 2001 14:47:30 GMT
Raw View
John Nagle wrote:
>
> Stephen Howe wrote:
> >
> > Is this valid according to the standard:
>
> >   string         s = s;
> >   vector<string> v = v;
>
>    Clearly it's not going to work, because it contains a reference to
> a variable before it has been constructed.  Generally, it's considered
> the job of the scoping system to prevent such references. The question
> is what scope applies in the right side of an initializer.
>

"[basic.scope.pdecl]
3.3.1 Point of declaration

1 The point of declaration for a name is immediately after its complete
declarator (clause 8) and before its
initializer (if any), except as noted below. [Example:

int x = 12;
{ int x = x; }

Here the second x is initialized with its own (indeterminate) value. ]"


This is sometimes useful, as when the initialization requires the
initialized object's address or size.



      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ 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.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]






Author: Pete Becker <petebecker@acm.org>
Date: 25 Sep 2001 14:47:29 GMT
Raw View
Allan W wrote:
>
> The reason that I bring this up is, that same convention says
> there's no need to have this type of guard for copy constructors,
> because construction as copy of self is meaningless.
>
> And yet, here you've provided evidence to the contrary.
>

But the two aren't at all comparable. The only way to initialize an
object with itself is with that code. There are lots of ways to end up
assigning an object to itself. And, of course, self-assignment has a
fairly obvious meaning, while self-initialization doesn't.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)



      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ 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.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]






Author: belvis@pacbell.net (Bob Bell)
Date: 20 Sep 2001 14:49:33 GMT
Raw View
plain; charset=ISO-8859-1
Content-Transfer-Encoding: 8bit
X-Trace: posting.google.com 1000933969 17891 127.0.0.1 (19 Sep 2001 21:12:49
GMT)
X-Complaints-To: groups-abuse@google.com
NNTP-Posting-Date: 19 Sep 2001 21:12:49 GMT
Content-Length: 169
ReSent-Date: Wed, 19 Sep 2001 16:08:07 -0700 (PDT)
ReSent-From: Steve Clamage <clamage@eng.sun.com>
ReSent-To:  <c++-submit@netlab.cs.rpi.edu>
ReSent-Subject: Re: Copy constructor invoked where RHS is itself?
ReSent-Message-ID: <Pine.SOL.4.33.0109191608070.2176@taumet>

> It gets past my compiler with no diagnostics and promptly blows up.
> I find this disturbing if it turns out that it is valid.

It is both valid and disturbing.

Bob



      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ 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.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]






Author: "Jeff Greif" <jgreif@spam-me-not.alumni.princeton.edu>
Date: 20 Sep 2001 14:49:33 GMT
Raw View
I would *guess* it's legal.  Many assignment operators have an identity
check (and punting of the rest of the operation when it's satisfied.)
If your implementation blows up, it may be missing this check and the
vendor would have a bug to fix if the assignment is legal (even if it is
pointless).

Jeff

"Stephen Howe" <SPAMstephen.howeGUARD@tnsofres.com> wrote in message
news:3ba87e8e$0$225$ed9e5944@reading.news.pipex.net...
>
> Is this valid according to the standard:
>
> >>>>>>>>>>>>>>>>>>
> #include <iostream>
> #include <string>
> #include <vector>
>
> using namespace std;
>
> int main() {
>   string         s = s;
>   vector<string> v = v;
>   v.push_back( s);
>   cout << "s = " << v[ 0] << endl;
>
>   return 0;
> }




      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ 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.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]






Author: Nicholas Leippe <nick@data-transit.com>
Date: 20 Sep 2001 16:15:59 GMT
Raw View
Stephen Howe wrote:
>
> Is this valid according to the standard:
>
> >>>>>>>>>>>>>>>>>>
> #include <iostream>
> #include <string>
> #include <vector>
>
> using namespace std;
>
> int main() {
>   string         s = s;
>   vector<string> v = v;
>   v.push_back( s);
>   cout << "s = " << v[ 0] << endl;
>
>   return 0;
> }
> >>>>>>>>>>>>>>>>>>
>
> It gets past my compiler with no diagnostics and promptly blows up.
> I find this disturbing if it turns out that it is valid.

This is undoubtedly valid syntax where the compiler's parser is
concerned, but I would expect it to blow up--it couldn't possibly do
otherwise.

It's passing a reference to itself to it's own copy ctor, which will
attempt to dereference itself while it is not yet initialized--boom.

Be glad it's obvious in this case--some classes may not actually
cause directly noticeable problems, depending on what their member
data is.  I can't think of why someone would need to try this
anyways--it doesn't have any conceptual merit, which is probably why
the compiler writers didn't bother to add a test for this to issue a
warning.


Nick



      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ 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.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]






Author: Mark Radford <twonine@twonine.demon.co.uk>
Date: Thu, 20 Sep 2001 16:52:50 GMT
Raw View
In article <3ba87e8e$0$225$ed9e5944@reading.news.pipex.net>, Stephen
Howe <SPAMstephen.howeGUARD@tnsofres.com> writes

>Is this valid according to the standard:
[...]
>int main() {
>  string         s = s;

Legal!

>  vector<string> v = v;

Legal!

>It gets past my compiler with no diagnostics and promptly blows up.
>I find this disturbing if it turns out that it is valid.

AFAIK this is a C legacy.

In any definition/initialisation of the form

T v = x;

the variable v comes is in scope at the = sign. Therefore the
expression:

vector<string> v = v;

is a case of "self initialisation" - v is initialised with its own, as
yet undefined, value.

Note:

vector<string> v(v); // Error

Using parentheses you're safe from this - v will not be in scope until
the semicolon.

Hope this helps.

 ---
 Mark Radford (Opinions are my own unless explicitly stated otherwise)
 twoNine Computer Services Limited - C++, Design, Development, Consultancy
 http://www.twonine.demon.co.uk/computing.htm
 Find out about ACCU at www.accu.org

---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: "Siemel Naran" <SiemelNaran@KILL.att.worldnet.net>
Date: 20 Sep 2001 18:37:45 GMT
Raw View
"Stephen Howe" <SPAMstephen.howeGUARD@tnsofres.com> wrote in message

> int main() {
>   string         s = s;
>   vector<string> v = v;
>   v.push_back( s);
>   cout << "s = " << v[ 0] << endl;

The code is valid.  However, a good compiler will warn (or maybe give an
error) that you use 'v' before initializing it.


--
+++++++++++
Siemel Naran



      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ 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.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]






Author: John Nagle <nagle@animats.com>
Date: 20 Sep 2001 18:37:44 GMT
Raw View
Stephen Howe wrote:
>
> Is this valid according to the standard:

>   string         s = s;
>   vector<string> v = v;

   Clearly it's not going to work, because it contains a reference to
a variable before it has been constructed.  Generally, it's considered
the job of the scoping system to prevent such references. The question
is what scope applies in the right side of an initializer.

     John Nagle
     Animats



      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ 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.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]






Author: Ron Hunsinger <hunsinger@mac.com>
Date: 20 Sep 2001 22:28:28 GMT
Raw View
In article <3ba87e8e$0$225$ed9e5944@reading.news.pipex.net>, "Stephen
Howe" <SPAMstephen.howeGUARD@tnsofres.com> wrote:

> Is this valid according to the standard:
>
> >>>>>>>>>>>>>>>>>>
> #include <iostream>
> #include <string>
> #include <vector>
>
> using namespace std;
>
> int main() {
>   string         s = s;
>   vector<string> v = v;
>   v.push_back( s);
>   cout << "s = " << v[ 0] << endl;
>
>   return 0;
> }
> >>>>>>>>>>>>>>>>>>
>
> It gets past my compiler with no diagnostics and promptly blows up.
> I find this disturbing if it turns out that it is valid.

It is disturbing, and it is valid. The standard even mentions this
(admittedly bizarre) case:

    3.3.1/1 [basic.scope.pdecl]
        The point of declaration for a name is immediately after its
        complete declarator (clause 8) and before its initializer
        (if any), except as noted below. [Example:

            int x = 12;
            { int x = x; }

        Here the second x is initialized with its own (indeterminate)
        value. ]

I'm guessing that the reason for allowing an object to participate in
its own initialization is to allow initializations like the following:

    struct node {
        node *next;
        node *prev;
        int value; }

    node empty = { &empty, &empty, 0 };


    const int size_of_int = sizeof(size_of_int);


    struct buffered_object {
        char small_buffer[10];
        char *active_buffer;
        buffered_object (char *buffer_to_use);
        //...
        };

    buffered_object small_one (small_one.small_buffer);


where the initializer is computable (using sizeof or operator& on the
object or its subobject) even before the object has been constructed.

These are admittedly not particularly compelling examples. Maybe
someone else can come up with some better ones.

-Ron Hunsinger

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ 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.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]






Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: 20 Sep 2001 23:20:54 GMT
Raw View
In article <3ba87e8e$0$225$ed9e5944@reading.news.pipex.net>, Stephen
Howe <SPAMstephen.howeGUARD@tnsofres.com> writes
>
>Is this valid according to the standard:
>
>>>>>>>>>>>>>>>>>>>
>#include <iostream>
>#include <string>
>#include <vector>
>
>using namespace std;
>
>int main() {
>  string         s = s;
Probable undefined behaviour, worse the compiler is required to compile
it unless it can demonstrate that the copy ctor of string cannot safely
use an unitialised string as the original.

>  vector<string> v = v;

I think the same applies.

>  v.push_back( s);
>  cout << "s = " << v[ 0] << endl;
>
>  return 0;
>}
>>>>>>>>>>>>>>>>>>>
>
>It gets past my compiler with no diagnostics and promptly blows up.
>I find this disturbing if it turns out that it is valid.
>
>Thanks
>

Francis Glassborow
I offer my sympathy and prayers to all those who are suffering
as a result of the events of September 11 2001.

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ 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.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]






Author: Pete Becker <petebecker@acm.org>
Date: 21 Sep 2001 15:11:35 GMT
Raw View
Stephen Howe wrote:
>
> Is this valid according to the standard:
>
> >>>>>>>>>>>>>>>>>>
> #include <iostream>
> #include <string>
> #include <vector>
>
> using namespace std;
>
> int main() {
>   string         s = s;
>   vector<string> v = v;
>   v.push_back( s);
>   cout << "s = " << v[ 0] << endl;
>
>   return 0;
> }
> >>>>>>>>>>>>>>>>>>
>
> It gets past my compiler with no diagnostics and promptly blows up.
> I find this disturbing if it turns out that it is valid.
>

int i = i; // undefined behavior, both in C and in C++

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)



      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ 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.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]






Author: kanze@gabi-soft.de (James Kanze)
Date: 21 Sep 2001 15:11:34 GMT
Raw View
plain; charset=ISO-8859-1
Content-Transfer-Encoding: 8bit
X-Trace: posting.google.com 1000991202 29028 127.0.0.1 (20 Sep 2001 13:06:42 GMT)
X-Complaints-To: groups-abuse@google.com
NNTP-Posting-Date: 20 Sep 2001 13:06:42 GMT
Content-Length: 1322

"Stephen Howe" <SPAMstephen.howeGUARD@tnsofres.com> wrote in message
news:<3ba87e8e$0$225$ed9e5944@reading.news.pipex.net>...
> Is this valid according to the standard:

The behavior of your compiler is valid.

> >>>>>>>>>>>>>>>>>>
> #include <iostream>
> #include <string>
> #include <vector>

> using namespace std;

> int main() {
>   string         s = s;

Initialize the string by copying the uninitialized value into it.

>   vector<string> v = v;

Ditto vector.

>   v.push_back( s);
>   cout << "s = " << v[ 0] << endl;

>   return 0;
> }
> >>>>>>>>>>>>>>>>>>

> It gets past my compiler with no diagnostics and promptly blows up.
> I find this disturbing if it turns out that it is valid.

In both cases, you are initializing the object with an uninitialized
object (itself).  Initializing with an uninitialized object is
undefined behavior.

Note that with other classes, this might be valid.  In both cases, the
constructor takes a reference; if it simply saves the reference for
later use (after the object is constructed), this is fine.

--
James Kanze                                   mailto:kanze@gabi-soft.de
Beratung in objektorientierer Datenverarbeitung --
                             -- Conseils en informatique orient   e objet
Ziegelh   ttenweg 17a, 60598 Frankfurt, Germany, T   l.: +49 (0)69 19 86 27



      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ 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.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]






Author: tinct@163.com (Tinct)
Date: 21 Sep 2001 15:11:35 GMT
Raw View
plain; charset=ISO-8859-1
Content-Transfer-Encoding: 8bit
X-Trace: posting.google.com 1000977927 25917 127.0.0.1 (20 Sep 2001 09:25:27 GMT)
X-Complaints-To: groups-abuse@google.com
NNTP-Posting-Date: 20 Sep 2001 09:25:27 GMT
Content-Length: 700

My Test Program: (under VC6/BCC 5)

#include <iostream>
using namespace std;
struct A {
 int nothing;
 A(void){cout << "CON_VOID\n";};
 A(const A&){cout << "CON_COPY\n";};
 A operator=(const A&){cout << "OP =\n";return * this;};
 };

void main()
{
  cout << "A a\n";
  A a;                // OUT: CON_VOID
  cout << "A b = a\n";
  A b = a;            // OUT: CON_COPY
  cout << "A c = c\n";
  A c = c;            // OUT: CON_COPY
  int i = i;          // For simple type
}

I checked the ASM code and found that the complier treat c as an
initialized object and call "copy construct function". It may be
something wrong. The compiler should give out an error.

Should complier give out a warning



      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ 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.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]






Author: kanze@gabi-soft.de (James Kanze)
Date: Fri, 21 Sep 2001 16:51:43 GMT
Raw View
Mark Radford <twonine@twonine.demon.co.uk> wrote in message
news:<3jyGXRAGvcq7EwhM@twonine.demon.co.uk>...
> In article <3ba87e8e$0$225$ed9e5944@reading.news.pipex.net>, Stephen
> Howe <SPAMstephen.howeGUARD@tnsofres.com> writes

> >Is this valid according to the standard:
>  [...]
> >int main() {
> >  string         s = s;

> Legal!

> >  vector<string> v = v;

> Legal!

> >It gets past my compiler with no diagnostics and promptly blows up.
> >I find this disturbing if it turns out that it is valid.

> AFAIK this is a C legacy.

It's true that similar code is legal in C.  But in the case of C++,
there are actually cases where it makes sense.

> In any definition/initialisation of the form

> T v = x;

> the variable v comes is in scope at the = sign. Therefore the
> expression:

> vector<string> v = v;

> is a case of "self initialisation" - v is initialised with its own,
> as yet undefined, value.

It's actually slightly more subtle.  While it is not the case for
std::string or std::vector, it is entirely possible to write a class
for which such initialization makes sense.

> Note:

> vector<string> v(v); // Error

> Using parentheses you're safe from this - v will not be in scope
> until the semicolon.

Not according to the standard.  When the symbol becomes visible isn't
(directly) dependant on any particular character.  According to
3.3.1/1, "The point of declaration for a name is immediately after its
complete declarator (clause 8) and before its initializer (if any),
except as noted below."  In the above, the (v) is an initializor, and
not part of the declarator.  (See also the grammar in chapter 8.)  The
above is just as legal as v = v.

--
James Kanze                                   mailto:kanze@gabi-soft.de
Beratung in objektorientierer Datenverarbeitung --
                             -- Conseils en informatique orient   e objet
Ziegelh   ttenweg 17a, 60598 Frankfurt, Germany, T   l.: +49 (0)69 19 86 27

---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: Fri, 21 Sep 2001 22:47:05 GMT
Raw View
In article <3jyGXRAGvcq7EwhM@twonine.demon.co.uk>, Mark Radford
<twonine@twonine.demon.co.uk> writes
>vector<string> v(v); // Error
>
>Using parentheses you're safe from this - v will not be in scope until
>the semicolon.

Actually no, as Martin O'Riordan pointed out to me a couple of years
ago, the rule applies to both forms, the initialiser in each case will
be the just declared v.


Francis Glassborow
I offer my sympathy and prayers to all those who are suffering
as a result of the events of September 11 2001.

---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: "Stephen Howe" <SPAMstephen.howeGUARD@tnsofres.com>
Date: 19 Sep 2001 15:16:51 GMT
Raw View
Is this valid according to the standard:

>>>>>>>>>>>>>>>>>>
#include <iostream>
#include <string>
#include <vector>

using namespace std;

int main() {
  string         s = s;
  vector<string> v = v;
  v.push_back( s);
  cout << "s = " << v[ 0] << endl;

  return 0;
}
>>>>>>>>>>>>>>>>>>

It gets past my compiler with no diagnostics and promptly blows up.
I find this disturbing if it turns out that it is valid.

Thanks

Stephen Howe




      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ 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.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]