473,394 Members | 2,031 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,394 software developers and data experts.

In place construction without placement new

Suppose that I have a class A with a constructor A(B b, C c) and I want
to make a vector of A's. Also, suppose that A's are VERY expensive to
construct, copy, assign. I also want to have a very many vectors of A's
and cannot afford to store a smart pointer to each A as the type in my
vectors.. So I want to write something like:

v.push_back(A(b1,c1));

and not have a sequence which goes like:

.... make space for an A in v at v[i]...
construct A() in v[i]
destruct v[i]
assign A(b1,c1) to v[i]

Unfortunately, this is the behaviour I am seeing in my compiler. I want:

.... make space for an A in v at v[i]...
construct A(b1,c1) in v[i]

Is there any known way to ensure that compilers will give the latter
code? I have a work around, but it is clunky...

Cheers

David

Jul 22 '05 #1
4 3698
* David:
Suppose that I have a class A with a constructor A(B b, C c) and I want
to make a vector of A's. Also, suppose that A's are VERY expensive to
construct, copy, assign.
Then a raw vector is contraindicated.

I also want to have a very many vectors of A's
and cannot afford to store a smart pointer to each A as the type in my
vectors..
Why?

So I want to write something like:

v.push_back(A(b1,c1));
You don't: no matter what you do you will then have construction of the
argument followed by copying of the argument.

and not have a sequence which goes like:

... make space for an A in v at v[i]...
construct A() in v[i]
destruct v[i]
assign A(b1,c1) to v[i]
That is a quality-of-implementation issue. The implementation should
just copy-construct the argument in the new space. However, given your
earlier remarks even that seems to be one copy-operation too much.

Unfortunately, this is the behaviour I am seeing in my compiler. I want:

... make space for an A in v at v[i]...
construct A(b1,c1) in v[i]

Is there any known way to ensure that compilers will give the latter
code?


No, but you can easily do it yourself.

Off the cuff:
class ConstructorArguments { ... };

class A
{
protected:
A( A const& another ) { ... }
A( ConstructorArguments const& a ) { ... };
A& operator=( A const& other ) { ... }
public:
virtual ~A() { ... }
};
class AVec
{
private:
static ConstructorArguments const* theArgs;

class AWrapper: public A
{
public:
AWrapper(): A( *theArgs ) {}

// Required for std::vector usage.
AWrapper( AWrapper const& another ): A( another ) {}
AWrapper& operator=( AWrapper const& other ) { ... }
};

std::vector<AWrapper> myVector;

public:
AVec( size_t aCapacity ) { myVector.reserve( aCapacity ); }

void pushBackNew( ConstructorArguments const& args )
{
if( myVector.size() == myVector.capacity() )
{
throw std::runtime_error( "Ooops, this would copy" );
}
theArgs = &args;
myVector.resize( myVector.size() + 1 );
}

A& operator[]( size_t i ) { return myVector[i]; }
A const& operator[]( size_t i ) const { return myVector[i]; }
};
assuming 'resize' constructs and does not subsequently assign (check it
out).

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 22 '05 #2
On 2004-11-27 23:22:24 +1100, al***@start.no (Alf P. Steinbach) said:
* David:
Suppose that I have a class A with a constructor A(B b, C c) and I want
to make a vector of A's. Also, suppose that A's are VERY expensive to
construct, copy, assign.
Then a raw vector is contraindicated.

I also want to have a very many vectors of A's and cannot afford to
store a smart pointer to each A as the type in my vectors..


Why?


Very large numbers of them all of which are unique pointers (i.e. apart
from algorithm use, their use count will sit at 1 for the majority of
their existence). So I'd prefer to store them by value, avoiding the
time and space overhead of a smart pointer for each of them and just
passing iterators/references to the items in the vectors.

So I want to write something like:

v.push_back(A(b1,c1));
You don't: no matter what you do you will then have construction of the
argument followed by copying of the argument.

and not have a sequence which goes like:

... make space for an A in v at v[i]...
construct A() in v[i]
destruct v[i]
assign A(b1,c1) to v[i]


That is a quality-of-implementation issue. The implementation should
just copy-construct the argument in the new space. However, given your
earlier remarks even that seems to be one copy-operation too much.


Yes I want to avoid all copying.

Unfortunately, this is the behaviour I am seeing in my compiler. I want:

... make space for an A in v at v[i]...
construct A(b1,c1) in v[i]

Is there any known way to ensure that compilers will give the latter code?


No, but you can easily do it yourself.

Off the cuff:
class ConstructorArguments { ... };

class A
{
protected:
A( A const& another ) { ... }
A( ConstructorArguments const& a ) { ... };
A& operator=( A const& other ) { ... }
public:
virtual ~A() { ... }
};
class AVec
{
private:
static ConstructorArguments const* theArgs;

class AWrapper: public A
{
public:
AWrapper(): A( *theArgs ) {}

// Required for std::vector usage.
AWrapper( AWrapper const& another ): A( another ) {}
AWrapper& operator=( AWrapper const& other ) { ... }
};

std::vector<AWrapper> myVector;

public:
AVec( size_t aCapacity ) { myVector.reserve( aCapacity ); }

void pushBackNew( ConstructorArguments const& args )
{
if( myVector.size() == myVector.capacity() )
{
throw std::runtime_error( "Ooops, this would copy" );
}
theArgs = &args;
myVector.resize( myVector.size() + 1 );
}

A& operator[]( size_t i ) { return myVector[i]; }
A const& operator[]( size_t i ) const { return myVector[i]; }
};
assuming 'resize' constructs and does not subsequently assign (check it
out).


Thanks for the suggestion!

I checked out the implementation and it calls insert (or erase, which
won't happen in my case) which then calls std::fill_n() which uses
operator=. I think that I then am back to quality of implementation? My
'clunky' solution is not all that different from your solution. I think
I may need to sleep on this one!

Cheers

David

Jul 22 '05 #3
* David:

I checked out the implementation and it calls insert (or erase, which
won't happen in my case) which then calls std::fill_n() which uses
operator=.


Well then, give it an AWrapper::operator=. One that doesn't do
anything. For the code to be portable you should do that anyway, now
that I think of it.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 22 '05 #4
* Alf P. Steinbach:
* David:

I checked out the implementation and it calls insert (or erase, which
won't happen in my case) which then calls std::fill_n() which uses
operator=.


Well then, give it an AWrapper::operator=. One that doesn't do
anything. For the code to be portable you should do that anyway, now
that I think of it.


Forgot to add: class A then needs a constructor that gives it a dummy
state, invoked by default constructor of AWrapper.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 22 '05 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

11
by: Peter Olcott | last post by:
I have just built a class that provides the most useful subset of std::vector functionality for use by compilers that lack template capability. http://home.att.net/~olcott/std_vect.html ...
2
by: Steve | last post by:
Hi Folks, Sorry for this stupid question, but how do you handle errors during class construction. In other words, if I have a class that loads a file, and during loading, an error occurs, how do...
23
by: Giancarlo Niccolai | last post by:
Hello all. I have peeked through the FAQ and all relevant links, and also through Stroustrup book, but I have not been able to find an answer, so I have to post here as a last resort. It...
20
by: Ioannis Vranos | last post by:
When we use the standard placement new operator provided in <new>, and not a definition of owr own, isn't a call to placement delete enough? Consider the code: #include <new>
14
by: trying_to_learn | last post by:
i am on the chapter on copy construction in C++ in the code (see below), the author says if u pass the object by value as in HowMany h2 = f(h); ....then a bitwise object is created w/o calling...
8
by: elviin | last post by:
Hello. I tried a sample programm using placement new. I am not sure if i understand this technique correctly. I do not mean usage but a real world application. Could anyone to describe some...
9
by: Ulrich Hobelmann | last post by:
Hi, slowly transitioning from C to C++, I decided to remodel a struct/union (i.e. type identifier as first field, union of variant types) as a class + subclasses. Switching functions are replaced...
4
by: marcus hall | last post by:
I am considering a strategy for implementation of a finite state machine. What I would like to do is to use derived classes to represent the state of the machine, so the vtable pointer is the state...
15
by: LuB | last post by:
I am constantly creating and destroying a singular object used within a class I wrote. To save a bit of time, I am considering using 'placement new'. I guess we could also debate this decision -...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.