Topic: Copy-initialization by itself (T a = a) allowed?


Author: "James Kanze" <james.kanze@gmail.com>
Date: Tue, 2 Jan 2007 12:22:01 CST
Raw View
Niels Dekker - no return address wrote:
> My compiler doesn't complain when I accidentally copy-initialize a
> variable by itself:
>   T a = a;

As it shouldn't.  It's not generally useful, but there are some
special cases where it might be, and the standard definitly says
that a goes into scope at the end of the declarator (but before
the initializer).  Obviously, you can't do anything which would
cause the reference to the variable to be dereferenced, but such
an initialization is both legal and possibly useful in cases
like:

    struct A
    {
        A const* next ;
        A( A const& other )
            :   next( &other )
        {
        }
    } ;

> On the other hand, the equivalent direct-initialization form is rejected
> as being ill-formed:
>   T a(a);

That's an error in the compiler, then.  The standard is quite
clear: the variable being declared goes into scope at the end of
the declarator, and before any initializer.

> Are those two forms really supposed to be treated differently?  Aren't
> they both ill-formed?

Neither is ill formed.

> Some classes apparently cannot deal with self-initialization.  The
> following line just causes a crash on the implementation I'm currently
> using:
>   std::vector<int> v = v;  // <-- Crash!!!

Nothing surprising there.  As you say, most classes cannot deal
with self-initialization.  Others can, however, and the standard
allows it.

--
James Kanze (Gabi Software)            email: james.kanze@gmail.com
Conseils en informatique orient   e objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place S   mard, 78210 St.-Cyr-l'   cole, France, +33 (0)1 30 23 00 34


---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: "Joshua Lehrer" <usenet_cpp@lehrerfamily.com>
Date: Tue, 26 Dec 2006 17:20:41 CST
Raw View
Niels Dekker - no return address wrote:
> My compiler doesn't complain when I accidentally copy-initialize a
> variable by itself:
>   T a = a;
>

Nor should it.

>
> Some classes apparently cannot deal with self-initialization.  The
> following line just causes a crash on the implementation I'm currently
> using:
>   std::vector<int> v = v;  // <-- Crash!!!

It is very difficult for a class to deal with self-initialization,
except to detect the error and throw:

T::T(const T &rhs) {
 if (this==&rhs) throw;
}

>
> If copy-initialization by itself is allowed, I'd recommand an author of
> a class that cannot deal with it, to add an "explicit" keyword to her
> copy constructor...  :-)
>

copy-initialization is not specifically allowed.  However, in your
example:

T v = v;

the name 'v' comes into scope at the equals sign.

The only example I've ever seen of where is than be slightly useful is
to detect if an object is being constructed const or not:

T::T(T& rhs) {
 if (this != &rhs) throw;
 //non-const constructor
}

T::T(const T& rhs) {
 if (this != &rhs) throw;
 //const constructor
}

T v = v; //non-const constructor called
const T v = v; //const-constructor called

However, as 'rhs' has not completed construction, any attempts to
access rhs are in error.

joshua lehrer
http://www.lehrerfamily.com/

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: Niels Dekker - no return address <unknown@this.is.invalid>
Date: Sun, 31 Dec 2006 14:05:40 CST
Raw View
Joshua Lehrer wrote:
> Niels Dekker wrote:
>> My compiler doesn't complain when I accidentally copy-initialize a
>> variable by itself:
>>   T a = a;
>
> Nor should it.

> It is very difficult for a class to deal with self-initialization,
> except to detect the error and throw:
>
> T::T(const T &rhs) {
>  if (this==&rhs) throw;
> }

Or it might just do a default construction of T, making "T v = v;"
equivalent to "T v;".

> copy-initialization is not specifically allowed.  However, in your
> example:
>
> T v = v;
>
> the name 'v' comes into scope at the equals sign.

I think I would have preferred it otherwise.  I would have preferred the
following program to return 0.  Instead, I guess it's a typical case of
undefined behaviour.

  int main() {
    short v = 0; {
      int v = v;
      return v;
    }
  }

Anyway, I promis myself not to write such silly programs again, in 2007
;-)

Thanks for your feedback, and a happy newyear!

  Niels Dekker

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: "Joshua Lehrer" <usenet_cpp@lehrerfamily.com>
Date: Mon, 1 Jan 2007 16:54:19 CST
Raw View
Niels Dekker - no return address wrote:
> I think I would have preferred it otherwise.  I would have preferred the
> following program to return 0.  Instead, I guess it's a typical case of
> undefined behaviour.
>
>   int main() {
>     short v = 0; {
>       int v = v;
>       return v;
>     }
>   }
>


I believe the reason the rules are written this way is for self
referential objects.  Consider creating an empty linked list with a
sential head and tail node:

struct node {
 node(node *prev, node *next);
 node *m_prev;
 node *m_next;
};

node *sentinel = new node(sentinel,sentinel);
node *head = sentinel;
node *tail = sentinel;

-josh

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: unknown@this.is.invalid (Niels Dekker - no return address)
Date: Sun, 24 Dec 2006 23:44:04 GMT
Raw View
My compiler doesn't complain when I accidentally copy-initialize a
variable by itself:
  T a = a;

On the other hand, the equivalent direct-initialization form is rejected
as being ill-formed:
  T a(a);

Are those two forms really supposed to be treated differently?  Aren't
they both ill-formed?

Some classes apparently cannot deal with self-initialization.  The
following line just causes a crash on the implementation I'm currently
using:
  std::vector<int> v = v;  // <-- Crash!!!

If copy-initialization by itself is allowed, I'd recommand an author of
a class that cannot deal with it, to add an "explicit" keyword to her
copy constructor...  :-)


Nice X-mas,

  Niels Dekker
  http://www.xs4all.nl/~nd/dekkerware
  C++ programmer at LKEB, Leiden University Medical Center

---
[ 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.comeaucomputing.com/csc/faq.html                      ]