By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
448,671 Members | 1,637 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 448,671 IT Pros & Developers. It's quick & easy.

How to avoid the use of copy constructor when using STL container function (push_back, etc.)

P: n/a
The following program calls the normal constructor and the copy
constructor.
By calling the copy constuctor is redundandant, all I want is only a
vector of a trial object.

Is there any way to avoid the use of the copy constructor?

#include <vector>
#include <iostream>

class trial {
public:
trial(int i) {
std::cout << "In constructor" << std::endl;
}
trial(const trial &) {
std::cout << "In copy constructor." << std::endl;
}
};

int main()
{
std::vector<trial> v;
v.push_back(trial(10));
}

/**************output
In constructor.
In copy constructor.
************************/

Apr 1 '06 #1
Share this Question
Share on Google+
11 Replies


P: n/a
In article <11*********************@t31g2000cwb.googlegroups. com>,
"Pe*******@gmail.com" <Pe*******@gmail.com> wrote:
The following program calls the normal constructor and the copy
constructor.
By calling the copy constuctor is redundandant, all I want is only a
vector of a trial object.

Is there any way to avoid the use of the copy constructor?

#include <vector>
#include <iostream>

class trial {
public:
trial(int i) {
std::cout << "In constructor" << std::endl;
}
trial(const trial &) {
std::cout << "In copy constructor." << std::endl;
} ~trial() {
std::cout << "In destructor." << std::endl;
} };

int main()
{
std::vector<trial> v;
v.push_back(trial(10));
}

/**************output
In constructor.
In copy constructor. In destructor. ************************/


The copy constructor call is not redundant. The vector cannot store the
temporary object you created because it will go out of scope as soon as
the next sequence point is reached. The vector must make a copy of the
trial object to store.
--
Magic depends on tradition and belief. It does not welcome observation,
nor does it profit by experiment. On the other hand, science is based
on experience; it is open to correction by observation and experiment.
Apr 1 '06 #2

P: n/a

Pe*******@gmail.com skrev:
The following program calls the normal constructor and the copy
constructor.
By calling the copy constuctor is redundandant, all I want is only a
vector of a trial object.
The copyconstructor is not redundant - it has to be there in order to
copy your object into the vector.
There is a proposal on the way that enables moving object - e.g. during
construction. It would not do anything for your case, however. A move
is typically quite effiecient for small objects.

/Peter
Is there any way to avoid the use of the copy constructor?

#include <vector>
#include <iostream>

class trial {
public:
trial(int i) {
std::cout << "In constructor" << std::endl;
}
trial(const trial &) {
std::cout << "In copy constructor." << std::endl;
}
};

int main()
{
std::vector<trial> v;
v.push_back(trial(10));
}

/**************output
In constructor.
In copy constructor.
************************/


Apr 1 '06 #3

P: n/a
Pe*******@gmail.com wrote:
The following program calls the normal constructor and the copy
constructor.
By calling the copy constuctor is redundandant, all I want is only a
vector of a trial object.

Is there any way to avoid the use of the copy constructor?

#include <vector>
#include <iostream>

class trial {
public:
trial(int i) {
std::cout << "In constructor" << std::endl;
}
trial(const trial &) {
std::cout << "In copy constructor." << std::endl;
}
};

int main()
{
std::vector<trial> v;
v.push_back(trial(10));
}

/**************output
In constructor.
In copy constructor.
************************/

STL containers take elements by value. One suggestion is to use a
container of smart pointers appropriate to your task. Then the copy
is only copying the pointer class. Boost has a number of smart
pointers you can choose from.

BTW, do not use the standard library auto_ptr. Due to it's copy
semantics, it is not appropriate for use in STL containers.

Apr 1 '06 #4

P: n/a
PengYu.UT wrote:
Is there any way to avoid the use of the copy constructor?
Why avoid it? Have you proven that this one little copy makes your program
slow? If your program is fast, stay with simple techniques that make your
program easy to debug and grow.
std::vector<trial> v;


If you switch to <trial*>, then you will need to call delete on each item in
the vector. But pointer copies will be very efficient.

Generally, std::auto_ptr<trial> could safely delete a pointer, but you
should not store auto_ptr inside any STL container (or most other
containers).

The next step is a shared smart pointer, such as boost::shared_ptr. Only
invest in a vector<boost::shared_ptr<trial> > after you prove you need it.
Copying a small object may be faster than copying a shared pointer.

--
Phlip
http://www.greencheese.org/ZeekLand <-- NOT a blog!!!
Apr 1 '06 #5

P: n/a
An**********@gmail.com wrote:
BTW, do not use the standard library auto_ptr. Due to it's copy
semantics, it is not appropriate for use in STL containers.


Any fully compliant C++ compiler will not allow you to do a push_back
to a container of std::vector<auto_ptr<T> > type.
---------------------------------------------------------------------------*-------------

David Maisonave
http://axter.com

Author of policy smart pointers (http://axter.com/smartptr)
Top ten member of C++ Expert Exchange:
http://www.experts-exchange.com/Cplusplus
---------------------------------------------------------------------------*-------------

Apr 2 '06 #6

P: n/a
Pe*******@gmail.com wrote:
The following program calls the normal constructor and the copy
constructor.
By calling the copy constuctor is redundandant, all I want is only a
vector of a trial object.

Is there any way to avoid the use of the copy constructor?


You can use a clone smart pointer like the following:
http://code.axter.com/copy_ptr.h

---------------------------------------------------------------------------*-------------

David Maisonave
http://axter.com

Author of policy smart pointers (http://axter.com/smartptr)
Top ten member of C++ Expert Exchange:
http://www.experts-exchange.com/Cplusplus
---------------------------------------------------------------------------*-------------

Apr 2 '06 #7

P: n/a
Axter wrote:
An**********@gmail.com wrote:
BTW, do not use the standard library auto_ptr. Due to it's copy
semantics, it is not appropriate for use in STL containers.


Any fully compliant C++ compiler will not allow you to do a push_back
to a container of std::vector<auto_ptr<T> > type.


Where in the standard did you find that? The closest I found is [20.4.5/3]:

[...] auto_ptr does not meet the CopyConstructible and Assignable
requirements for Standard Library container elements and thus
instantiating a Standard Library container with an auto_ptr results
in undefined behavior.

This quote says it's undefined behavior. You seem to claim that it is an
error and diagnostics is required.
Best

Kai-Uwe Bux
Apr 2 '06 #8

P: n/a
Kai-Uwe Bux wrote:
Any fully compliant C++ compiler will not allow you to do a push_back
to a container of std::vector<auto_ptr<T> > type.


Where in the standard did you find that? The closest I found is
[20.4.5/3]:

[...] auto_ptr does not meet the CopyConstructible and Assignable
requirements for Standard Library container elements and thus
instantiating a Standard Library container with an auto_ptr results
in undefined behavior.

This quote says it's undefined behavior. You seem to claim that it is an
error and diagnostics is required.


If the Standard doesn't define "not allow", then your quote indeed sets the
bounds where programmers should not allow themselves to go.

--
Phlip
http://www.greencheese.org/ZeekLand <-- NOT a blog!!!
Apr 2 '06 #9

P: n/a

"Kai-Uwe Bux" <jk********@gmx.net> skrev i meddelandet
news:e0**********@murdoch.acc.Virginia.EDU...
Axter wrote:
An**********@gmail.com wrote:
BTW, do not use the standard library auto_ptr. Due to it's copy
semantics, it is not appropriate for use in STL containers.


Any fully compliant C++ compiler will not allow you to do a
push_back
to a container of std::vector<auto_ptr<T> > type.


Where in the standard did you find that? The closest I found is
[20.4.5/3]:

[...] auto_ptr does not meet the CopyConstructible and Assignable
requirements for Standard Library container elements and thus
instantiating a Standard Library container with an auto_ptr results
in undefined behavior.

This quote says it's undefined behavior. You seem to claim that it
is an
error and diagnostics is required.


One possible outcome of undefined behavior is a diagnostic.

Class auto_ptr is defined in such a way that a diagnosable error is
*highly likely* to occur, if you use it in a standard container. It is
not strictly required though.
Bo Persson
Apr 2 '06 #10

P: n/a
Kai-Uwe Bux wrote:
Axter wrote:
An**********@gmail.com wrote:
BTW, do not use the standard library auto_ptr. Due to it's copy
semantics, it is not appropriate for use in STL containers.


Any fully compliant C++ compiler will not allow you to do a push_back
to a container of std::vector<auto_ptr<T> > type.


Where in the standard did you find that? The closest I found is [20.4.5/3]:

[...] auto_ptr does not meet the CopyConstructible and Assignable
requirements for Standard Library container elements and thus
instantiating a Standard Library container with an auto_ptr results
in undefined behavior.

This quote says it's undefined behavior. You seem to claim that it is an
error and diagnostics is required.


IAW the standard it is considered undefined behavior to instantiate
this type, but that's not what I'm referring to, and that's why I
specified push_back call for auto_ptr type.

std::vector<auto_ptr<T> > ptr; //This is undefined IAW C++ standard

ptr.push_back(auto_ptr<T>(new T)); //This is not allowed IAW C++
standard
IAW the standard, you can NOT perform a push_back of an auto_ptr<T> to
a container of auto_ptr<T>.
The standard doesn't explicitly state this, and it would be hard for it
to do so on a type that is undefined.
But it does disallow it indirectly, since the standard clearly defines
an auto_ptr copy constructor taking a non-constant type, and a
vector::push_back taking a constant type.
20.4.5.1 auto_ptr constructors
auto_ptr(auto_ptr &a) throw();

//23.2.4.3 modifiers
void push_back(const T& x);

So IAW C++ standard you can not perform a push_back of type auto_ptr<T>
on a container of auto_ptr<T>.

IAW C++ standard, your compiler may or may not let you declare a
container of auto_ptr<T>, but it can not let you populate it via
push_back.
----------------------------------------------------------------------------------------
David Maisonave
http://axter.com
----------------------------------------------------------------------------------------

Apr 3 '06 #11

P: n/a
Axter wrote:
Kai-Uwe Bux wrote:
Axter wrote:
> An**********@gmail.com wrote:
>> BTW, do not use the standard library auto_ptr. Due to it's copy
>> semantics, it is not appropriate for use in STL containers.
>
> Any fully compliant C++ compiler will not allow you to do a push_back
> to a container of std::vector<auto_ptr<T> > type.
Where in the standard did you find that? The closest I found is
[20.4.5/3]:

[...] auto_ptr does not meet the CopyConstructible and Assignable
requirements for Standard Library container elements and thus
instantiating a Standard Library container with an auto_ptr results
in undefined behavior.

This quote says it's undefined behavior. You seem to claim that it is an
error and diagnostics is required.

[snip] But it does disallow it indirectly, since the standard clearly defines
an auto_ptr copy constructor taking a non-constant type, and a
vector::push_back taking a constant type.
20.4.5.1 auto_ptr constructors
auto_ptr(auto_ptr &a) throw();

//23.2.4.3 modifiers
void push_back(const T& x);

So IAW C++ standard you can not perform a push_back of type auto_ptr<T>
on a container of auto_ptr<T>.

IAW C++ standard, your compiler may or may not let you declare a
container of auto_ptr<T>, but it can not let you populate it via
push_back.


Hm, I think you are reading too much into the signatures. Consider the
following (absolutely unlikely and bad) implementation of std::vector:
#include <cstddef>
#include <memory>
#include <cassert>

namespace std {

template < typename T, typename A = std::allocator<T> >
struct vector {

typedef std::size_t size_type;
typedef T value_type;
typedef T * pointer;
typedef T const * const_pointer;
typedef T & reference;
typedef T const & const_reference;

private:

pointer the_data;
size_type the_size;
size_type the_cap;

public:

// ...

void push_back ( const_reference c_ref ) {
if ( the_size == the_cap ) {
// do some fancy reallocation stuff
}
assert( the_size < the_cap );
new ( the_data + the_size )
value_type ( const_cast<reference>( c_ref ) );
++ the_size;
}

}; // vector

} // namespace std
I would claim that this implementation is conforming:

a) it has the right signature.
b) for any type T that satisfies the conceptual requirements (like
CopyConstructible), it does the right thing.

This implementation will, however, not trigger an error message for
std::auto_ptr.
As a practical matter, of course, you are right: it is more than likely that
a compiler will give you an error. But I do not see why it would be
required to do so by the standard.

Best

Kai-Uwe Bux
Apr 3 '06 #12

This discussion thread is closed

Replies have been disabled for this discussion.