Copy Constructor for an Array Element ???

P

Peter Olcott

//
// Is there something wrong with my syntax for the
// Copy Constructor of an Array Element, or does
// the C++ language not support this?
//

#include <stdio.h>
#include <stdlib.h>

class X {
int Data;
public:
X() { Data = 56; };
X(const X& Y) { Data = Y.Data; }; // Copy Constructor
void Construct(const X& Y) { Data = Y.Data; };
};

int main()
{
X ABC;
X* Temp = (X*) malloc(sizeof(X) * 10);
for (int N = 0; N < 10; N++) {
// Temp[N].(ABC); // Does Not Compile
// Temp[N](ABC); // Does Not Compile
Temp[N].Construct(ABC); // Compiles and Executes Correctly
}
free(Temp);
return 0;
}
 
V

Victor Bazarov

Peter Olcott said:
//
// Is there something wrong with my syntax for the
// Copy Constructor of an Array Element, or does
// the C++ language not support this?

The latter. Constructors do not have names, therefore they cannot
be found during name lookup and hence cannot be _called_. They can
only be _invoked_ during construction of the object.

Given this situation, you'd be better off using _placement_new_
(read about it in a good C++ book).
//

#include <stdio.h>
#include <stdlib.h>

class X {
int Data;
public:
X() { Data = 56; };
X(const X& Y) { Data = Y.Data; }; // Copy Constructor
void Construct(const X& Y) { Data = Y.Data; };
};

int main()
{
X ABC;
X* Temp = (X*) malloc(sizeof(X) * 10);
for (int N = 0; N < 10; N++) {
// Temp[N].(ABC); // Does Not Compile
// Temp[N](ABC); // Does Not Compile
Temp[N].Construct(ABC); // Compiles and Executes Correctly
}
free(Temp);
return 0;
}

V
 
E

E. Robert Tisdale

Peter said:
//
// Is there something wrong with my syntax for the
// Copy Constructor of an Array Element, or does
// the C++ language not support this?
//

#include <stdio.h>
#include <stdlib.h>

class X {
private:
// representation
int Data;
public:
X(void): Data(56) { } // default
X(const X& Y): Data(Y.Data) { } // Copy Constructor
// void Construct(const X& Y) { Data = Y.Data; };
// too late. *this already constructed
X& modify(const X& Y) { Data = Y.Data; return *this; }
};

int main(int argc, char* argv[]) {
X ABC;
X* Temp = (X*)malloc(sizeof(X)*10); // you shouldn't do this
for (int N = 0; N < 10; ++N) {
Temp[N] = ABC; // uses default assignment
Temp[N].modify(ABC);
 
J

Jonathan Turkanis

Victor Bazarov said:
The latter. Constructors do not have names, therefore they cannot
be found during name lookup and hence cannot be _called_. They can
only be _invoked_ during construction of the object.

Given this situation, you'd be better off using _placement_new_
(read about it in a good C++ book).

I'd recommend using an assignment operator or a member function assign
(like std library containers) instead of placement new, unless you are
absolutely sure you need it.

And if you do use placement new to constuct an object on top of an
existing object, make sure to call the objects destructor first
(unless you are absolutely sure it's not necessary.)

Jonathan
 
P

Peter Olcott

I'd recommend using an assignment operator or a member function assign
(like std library containers) instead of placement new, unless you are
absolutely sure you need it.

I just created a std::vector class for antique (pre-template) C++ compilers.
My intention was to implement this within minimal execution time.
Apparently, it seems that even the modern std::vectors must use a kludge
to initialize their members. They seem to require default construction and
then assignment, rather than the single integrated step of copy construction.
Hopefully this shortcoming will by addressed in the continuing evolution
of C++.
 
C

Cy Edmunds

Peter Olcott said:
I just created a std::vector class for antique (pre-template) C++ compilers.
My intention was to implement this within minimal execution time.
Apparently, it seems that even the modern std::vectors must use a kludge
to initialize their members. They seem to require default construction and
then assignment, rather than the single integrated step of copy
construction.

[snip]

Well, not really:

std::vector<int> a;
a.reserve(3);
a.push_back(2);
a.push_back(4);
a.push_back(-2);

reserve just allocates enough space and a copy constructor is used for each
element. No default constructor and no assignment. The only inefficiency
that I know of is that the number of push_back's is counted.
 
P

Peter Olcott

class X {
private:
// representation
// too late. *this already constructed

I don't think so. I think that the example might be the only
way to copy construct array elements.
X& modify(const X& Y) { Data = Y.Data; return *this; }
};

int main(int argc, char* argv[]) {
X ABC;
X* Temp = (X*)malloc(sizeof(X)*10); // you shouldn't do this
for (int N = 0; N < 10; ++N) {
Temp[N] = ABC; // uses default assignment
Temp[N].modify(ABC);
}
free(Temp);
return 0;
}
 
P

Peter Olcott

std::vector said:
a.reserve(3);
a.push_back(2);
a.push_back(4);
a.push_back(-2);

reserve just allocates enough space and a copy constructor is used for each
element. No default constructor and no assignment. The only inefficiency
that I know of is that the number of push_back's is counted.
Try the same sort of example with a class that does memory allocation,
such that a deep copy (rather than bitwise) is required.
 
J

Jonathan Turkanis

Peter Olcott said:
Try the same sort of example with a class that does memory allocation,
such that a deep copy (rather than bitwise) is required.

Cy is correct.A vector obtains unitialized memory from an allocator,
and initilizes each element, when appropriate, then initializes them
using copy constructors with placement new. A default constructor is
not even required to exist. (See 20.1.4).

Of course, if the copy constructor is expensive, then push_back will
be too. There's no way to avoid this.

Jonathan
 
J

Jonathan Turkanis

Cy is correct.A vector obtains unitialized memory from an allocator,
and initilizes each element, when appropriate, then initializes them
using copy constructors with placement new. A default constructor is

This came out garbled. It should say:

A vector obtains unitialized memory from an allocator, then initilizes
each element, when appropriate, using copy constructors with placement
new

Jonathan
 
T

tom_usenet

//
// Is there something wrong with my syntax for the
// Copy Constructor of an Array Element, or does
// the C++ language not support this?

It does, via "placement new". See below.
//

#include <stdio.h>
#include <stdlib.h>

class X {
int Data;
public:
X() { Data = 56; };
X(const X& Y) { Data = Y.Data; }; // Copy Constructor
void Construct(const X& Y) { Data = Y.Data; };
};

int main()
{
X ABC;
X* Temp = (X*) malloc(sizeof(X) * 10);
for (int N = 0; N < 10; N++) {
// Temp[N].(ABC); // Does Not Compile
// Temp[N](ABC); // Does Not Compile
Temp[N].Construct(ABC); // Compiles and Executes Correctly

new (Temp + N) X(ABC); //placement construction
}
free(Temp);
return 0;
}

Tom
 
P

Peter Olcott

Cy is correct.A vector obtains unitialized memory from an allocator,
This came out garbled. It should say:

A vector obtains unitialized memory from an allocator, then initilizes
each element, when appropriate, using copy constructors with placement
new

Jonathan
I placed messages in every constructor and destructor of my class,
and had std::vector resize() itself. In both of my compilers the number
of elements constructed was one more than I asked for. This seems to
indicate that the compiler is somehow created an extra temporary
object.

I will look into this <placement new> more deeply, though.
 
P

Peter Olcott

tom_usenet said:
//
// Is there something wrong with my syntax for the
// Copy Constructor of an Array Element, or does
// the C++ language not support this?

It does, via "placement new". See below.
//

#include <stdio.h>
#include <stdlib.h>

class X {
int Data;
public:
X() { Data = 56; };
X(const X& Y) { Data = Y.Data; }; // Copy Constructor
void Construct(const X& Y) { Data = Y.Data; };
};

int main()
{
X ABC;
X* Temp = (X*) malloc(sizeof(X) * 10);
for (int N = 0; N < 10; N++) {
// Temp[N].(ABC); // Does Not Compile
// Temp[N](ABC); // Does Not Compile
Temp[N].Construct(ABC); // Compiles and Executes Correctly

new (Temp + N) X(ABC); //placement construction

None of my three compilers would accept this.
 
T

tom_usenet

None of my three compilers would accept this.

What was the error?

You need #include <new> at the top (or possibly <new.h> for
pre-standard compilers). Then it should be accepted by any recent
compiler, and certainly MSVC6+, GCC 2.95+, etc.

Tom
 
O

Old Wolf

E. Robert Tisdale said:
Peter Olcott wrote:

Of the 21 lines in Peter Olcott's posted program, only 6 were quoted
unmodified by Trollsdale.

If we ignore whitespace modifications, 10 lines were quoted unmodified
(less than half of the posted program). Is this a record?

Not to mention the fact that all of the supplied
modifications are wrong or irrelevant, and not helpful.
//
// Is there something wrong with my syntax for the
// Copy Constructor of an Array Element, or does
// the C++ language not support this?
//

#include <stdio.h>
#include <stdlib.h>

class X {
private:
// representation
int Data;
public:
X(void): Data(56) { } // default
X(const X& Y): Data(Y.Data) { } // Copy Constructor
// void Construct(const X& Y) { Data = Y.Data; };
// too late. *this already constructed
X& modify(const X& Y) { Data = Y.Data; return *this; }
};

int main(int argc, char* argv[]) {
X ABC;
X* Temp = (X*)malloc(sizeof(X)*10); // you shouldn't do this
for (int N = 0; N < 10; ++N) {
Temp[N] = ABC; // uses default assignment
Temp[N].modify(ABC);
}
free(Temp);
return 0;
}
 
P

Peter Olcott

If you have a copy of the ARM (annotated reference manual), I expect
that will present a pre-standard syntax that placement new replaced.
ARM presents C++ as implemented in CFront 3.0...

I don't have a copy of the book. You could try this:

#include <stdlib.h>
#include <stddef.h>

void* operator new(size_t size, void* ptr)
{
return ptr;
}

void* operator new[](size_t size, void* ptr)
{
return ptr;
}



class Foo{};

int main()
{
void* mem = malloc(sizeof(Foo));
Foo* p = new(mem) Foo();
}

That may or may not work...


Below is the "official" work-around. I also included the usenet URL where this material
was found. I could not get this work-around to work. Can you see why this would not
make the syntax that you provided function correctly?

//######### ######### ######### ######### ######### ######### ######### #########
//######### Bug report version 1.01.6 and earlier starts here #########
//######### ######### ######### ######### ######### ######### ######### #########
//
// Severity: Missing header file
// Workaround: Provided below
// Versions: Occurs in both TC++ 1.00 and 1.01
// Fixed in: Fixed in 2.0

// There is no <new.h>. I constructed the following work-alike. It should go
// into your standard include directory (where <iostream.h> is, for example):
// new.h
// Author: Dr. Marshall Cline/ECE Dept/Clarkson Univ/Potsdam,NY 13676
// Email: (e-mail address removed)
// Phone: Voice: 315-268-6511; Fax: 315-268-7600
// Copyright: The Author releases this to the Public Domain, 9-July-90.
// Date: 9-July-1990
// Please include these acknowledgements when distributing this file
#ifndef __NEW_H
#define __NEW_H
#ifndef _SIZE_T
#define _SIZE_T
typedef unsigned size_t;
#endif
void* operator new(size_t size, void* ptr);
// _new_handler is a ptr to a parameterless function returning void
extern void (*_new_handler)();
void (*set_new_handler(void (*replacement_handler)()))();
#endif __NEW_H

// Borland says:
// NEW.H is NOT defined by AT&T 2.0 C++ specs. The contents
// were in C++ specs 1.2 and is making a comeback in the
// upcoming ANSI C++ spec. We do have the underlying code, ie
// _new_handler support, but it is not documented. It would be
// nicer to use a typedef for the void function pointer, for the
// above work-around.
//
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// http://groups.google.com/[email protected]&oe=UTF-8
 
P

Peter Olcott

#include said:
#include <stddef.h>

void* operator new(size_t size, void* ptr)
{
return ptr;
}

void* operator new[](size_t size, void* ptr)
{
return ptr;
}



class Foo{};

int main()
{
void* mem = malloc(sizeof(Foo));
Foo* p = new(mem) Foo();
}

Preliminary indications are that this idea works.
I am still working through the details. Thanks for
your help.
 
P

Peter Olcott

void* operator new(size_t size, void* ptr)
{
return ptr;
}

This has become my <new> header file. This succinct advice, along with
the <placement new> syntax and instructions has amounted to more help
than everyone else put together. Since I was also able to stumble across the
Ye Olde syntax for delete[], (which is delete [int]) I will be able to adapt
my current std::vector (for pre-template compilers) so that it has identical
usage syntax and requirements the STL versions.

//
//
// A Turbo C++ 1.0 Workaround that permits <placement new>
// provided by "tom_usenet" <[email protected]> from
// the comp.lang.c++ newsgroup.
//
//
#pragma warn -par
void* operator new(size_t size, void* ptr)
{
return ptr;
}

Thanks again Tom for the excellent help !
 
R

Ron Natalie

Peter Olcott said:
It is this "possibly moving objects in the process" that I need to be able
to have a copy constructor for an array element.

It's one of the reasons. The other reason is to copy in the "fill" object
on resize. This avoids:
1. requiring a default constructor for the contained object.
2. creating an object that's just going to be copied over (a slight efficiency)
With modern compilers
this can be easily accomplished with <placement new>. This feature is
not available on AT&T 2.0, which is my required development platform.
Got any good ideas on the best way to do this?

Well, if you're willing to put some limitations on std::vector, for example that
the object must be default constructable, you could just default construct the
new allocation, and then use assignment.
 

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

Forum statistics

Threads
474,163
Messages
2,570,897
Members
47,436
Latest member
MaxD

Latest Threads

Top