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

P

PengYu.UT

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.
************************/
 
D

Daniel T.

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.
 
P

peter koch

(e-mail address removed) 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
 
A

AnonMail2005

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.
 
P

Phlip

PengYu.UT said:
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.
 
A

Axter

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
---------------------------------------------------------------------------­-------------
 
A

Axter

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
---------------------------------------------------------------------------­-------------
 
K

Kai-Uwe Bux

Axter said:
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
 
P

Phlip

Kai-Uwe Bux said:
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.
 
B

Bo Persson

Kai-Uwe Bux said:
Axter said:
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
 
A

Axter

Kai-Uwe Bux said:
Axter said:
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.
 
K

Kai-Uwe Bux

Axter said:
Kai-Uwe Bux said:
Axter said:
(e-mail address removed) 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
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top