🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.std.c++
Article #512

Re: new[] and constructor arguments

#512
From: Piercarlo Grandi
Date: Sat, 15 Sep 1990 18:48
126 lines
5052 bytes
On 12 Sep 90 17:57:01 GMT, rpk@rice-chex.ai.mit.edu (Robert Krajewski) said:

rpk> Does anybody else consider the fact that new[] only works with
rpk> default constructors (i.e., those with no parameters) to be a
rpk> blemish on the language ? [ ... ]

I think that the special treatment of arrays by operator new is the big
blemish.

The problem here is really that operator new really should allocate a
single object; if you use cast like parenthesization of abstract
declarators, you see that in

	typedef c100 complex[100];

	complex *c1 = new complex[100];
	complex *c2 = new c100;
	complex *c3 = new (complex[100]);

the last three lines *should be* exactly equivalent, and essentially
equivalent in turn to the last two lines of

	extern "C" extern void *malloc(size_t);

	complex *c4 = (complex *) malloc(sizeof (complex[100]));
	complex *c5 = (complex *) malloc(sizeof (c100));

because 'c100' is not a class type and therefore has no constructors or
destructors.

rpk> There are workarounds, I realize, like writing your own loop and
rpk> using operator new (size_t, void *).

This is not a workaround; it is a proper use of the abstraction
facilities of C++.

A strict interpretation like mine above would mean that users should be
made to define their own array type constructors; in other words, users
should make the 'c100' type explicit as a class, with a suitable
constructor to initialize each element, e.g. something like

	#include <complex.H>

	class cv
	{
	protected:
	    const unsigned n; complex *c;
	public:
	    cv(unsigned /* add further parameters as desired */); ~cv();
	    inline complex &operator[](unsigned);
	    // .....
	};

	#include <assert.H>

	// Under C++ 2.1 the static below regrettably is out
	static inline complex &cv::operator[](auto const unsigned i)
	{
	    assert (i >=0 && i < this->n,"cv::operator[]");
	    return &this->c[i];
	}

	extern "C" extern void *calloc(size_t,unsigned);
	extern "C" extern void free(void *);

	extern cv::cv(auto const unsigned e /* any other parameters */)
	: n(e), c(calloc(sizeof (complex),e))
	{
	    register complex *c;
	    register complex *const l = &this->c[e];

	    assert (this->c != 0,"cv::cv");

	    for (c = &this->c[0]; c < l; c++)
		(void) new((void *) c) (complex)(/* any other parameters */);
	}

	extern cv::~cv()
	{
	    register complex *c;
	    register complex *const l = &this->c[e];

	    for (c = &this->c[0]; c < l; c++)
		c->~complex();

	    free((void *) c);
	}

	// ... and so on merrily

In the absence of templates, this has been deemed too boring for users
to do for each type of array they want (even if you can get a lot of
mileage out of macros and using 'void *' and horrible pointer
arithmetic), so operator new does a special case for arrays, leading to
all that silly square bracketing with operator delete.

    Note that C++ 2.1 seems to imply that the above is more or less how
    the compiler is required to implement heap arrays now. Uhm.

rpk> Basically, I don't buy the argument in the bulletted item on page
rpk> 61 of E&S (section 5.3.3).  The compiler can easily generate
rpk> correct and efficient initialization code for this case where
rpk> parameters are passed.

The fundamental problem is that C++ inherits from C a weak definition of
arrays and the array type constructor, one that seems to be unacceptable
to users of C++ (which seem to require a definition of arrays that
implies keeping descriptors at run time); attempts to patch this
definition up so that it meets the expectation of C++ users without
jettisoning the C one altogether have caused quite a bit of confusion.

My idea: if the C++ users want arrays that behave like classes, let them
define their own array classes, and when they will have templates, they
can define just one template for each array arity.

XOR, junk the conventional C idea of the array type constructor, and
provide a C++-ish one. Halfway you basically get mostly trouble.

Incidentally, making the main argument to operator new be a parenthesis
enclosed abstract declarator (a cast), just like for the sizeof
operator, would remove one of the two most prominent causes of nasty
syntax ambiguities in C++.
--
Piercarlo "Peter" Grandi           | ARPA: pcg%uk.ac.aber.cs@nsfnet-relay.ac.uk
Dept of CS, UCW Aberystwyth        | UUCP: ...!mcsun!ukc!aber-cs!pcg
Penglais, Aberystwyth SY23 3BZ, UK | INET: pcg@cs.aber.ac.uk
Technical Details
Message-ID: <PCG.90Sep15194839@odin.cs.aber.ac.uk>
Path: arc1-ca.pugleaf.net!utzoo!attcan!utgpu!news-server.csri.toronto.edu!clyde.concordia.ca!uunet!mcsun!ukc!dcl-cs!aber-cs!athene!pcg
References: <10647@life.ai.mit.edu>

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!attcan!utgpu!news-server.csri.toronto.edu!clyde.concordia.ca!uunet!mcsun!ukc!dcl-cs!aber-cs!athene!pcg
From: pcg@cs.aber.ac.uk (Piercarlo Grandi)
Newsgroups: comp.std.c++
Subject: Re: new[] and constructor arguments
Message-ID: <PCG.90Sep15194839@odin.cs.aber.ac.uk>
Date: 15 Sep 90 18:48:39 GMT
References: <10647@life.ai.mit.edu>
Sender: pcg@aber-cs.UUCP
Organization: Coleg Prifysgol Cymru
Lines: 126
Nntp-Posting-Host: odin
In-reply-to: rpk@rice-chex.ai.mit.edu's message of 12 Sep 90 17:57:01 GMT