Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

A question on "uncopyable" that disable copy constructor

115 views
Skip to first unread message

TH

unread,
Feb 22, 2012, 11:45:34 PM2/22/12
to
Meyer's Effective C++ book talks about the case where you may want to disallow compiler generated copy constructor. The example is:

class HomeForSale {...}

It doesn't make sense to do:

HomeForSale h1(h2); or h1 = h2.

No problem. However, Does disallowing the copy constructor effectively prohibit it from putting such object into a container type, as

std::vector<HomeForSale> home_vec;
home_vec.push_back(h1); // need copy constructor??

It sounds like a severe constraints on the possible use of such object, am I missing anything?

Thanks

T.H.

Ian Collins

unread,
Feb 23, 2012, 12:33:28 AM2/23/12
to
On 02/23/12 05:45 PM, TH wrote:
> Meyer's Effective C++ book talks about the case where you may want to disallow compiler generated copy constructor. The example is:
>
> class HomeForSale {...}
>
> It doesn't make sense to do:
>
> HomeForSale h1(h2); or h1 = h2.
>
> No problem. However, Does disallowing the copy constructor effectively prohibit it from putting such object into a container type, as
>
> std::vector<HomeForSale> home_vec;
> home_vec.push_back(h1); // need copy constructor??

Yes.

> It sounds like a severe constraints on the possible use of such object, am I missing anything?

The reason not to allow copying? If it is inappropriate or too
expensive to copy a T, use a container of (smart) pointers to T.

--
Ian Collins

Miles Bader

unread,
Feb 23, 2012, 1:14:47 AM2/23/12
to
A typical example of a class where you don't want an automatically
generated copy-constructor is one that has pointer member which is
deallocated by the destructor; simply copying the pointer member into
a new object would cause obvious problems (as soon as the first of the
two object is destroyed, the pointer would be dangling).

The key point is that _any_ use of a default copy-constructor for such
classes -- _including_ copying by std::vector or whatever -- will
violate the invariants the class relies on, and cause problems. So
suppressing it for all uses is a feature. :)

Of course, often one then provides a user copy-constructor instead,
which does the right thing for copying (e.g. making a copy of the
pointed-to object in the above example).

However in some cases that's hard or maybe just annoying to implement
(maybe you'd need to add reference counting for shared resources, etc,
and for the class in question, such complexity would be unjustified by
the expect use). Then you just disable the auto-generated constructor
and write in the documentation "don't copy this."

Yeah that means you can't put it in std::vector, etc...

However as the decision to make the object uncopyable is usually done
with an eye towards expected usage, presumably such a class is one
where "putting it in a vector" is not expected. If you _really_ need
a vector of such objects, you can use a vector of pointers or
something instead (obviously you need to be careful and manage the
lifetimes of the pointed-to objects, but oh well).

-miles

--
Scriptures, n. The sacred books of our holy religion, as distinguished from
the false and profane writings on which all other faiths are based.

Jorgen Grahn

unread,
Feb 23, 2012, 3:47:40 AM2/23/12
to
On Thu, 2012-02-23, Ian Collins wrote:
> On 02/23/12 05:45 PM, TH wrote:
>> Meyer's Effective C++ book talks about the case where you may ...
>>
>> class HomeForSale {...}
>>
>> It doesn't make sense to do:
>>
>> HomeForSale h1(h2); or h1 = h2.
>>
>> No problem. However, Does disallowing the copy constructor...
>>
>> std::vector<HomeForSale> home_vec;
>> home_vec.push_back(h1); // need copy constructor??
>
> Yes.
>
>> It sounds like a severe constraints on the possible use of such object,
>> am I missing anything?
>
> The reason not to allow copying? If it is inappropriate or too
> expensive to copy a T, use a container of (smart) pointers to T.

It should be added though, that the uniqueness of a HomeForSale is not
enough reason to go crazy with smart pointers. If I saw a need to
place such a thing in a std::vector, I wouldn't hesitate to make it
copyable. I would also (reluctantly) add a default constructor if
needed, even though it means introducing "the nil home for sale".

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .

T.H.

unread,
Feb 23, 2012, 4:51:55 AM2/23/12
to

> A typical example of a class where you don't want an automatically
> generated copy-constructor is one that has pointer member which is
> deallocated by the destructor; simply copying the pointer member into
> a new object would cause obvious problems (as soon as the first of the
> two object is destroyed, the pointer would be dangling).
>
> The key point is that _any_ use of a default copy-constructor for such
> classes -- _including_ copying by std::vector or whatever -- will
> violate the invariants the class relies on, and cause problems.  So
> suppressing it for all uses is a feature.  :)

this "typical example" is very helpful to me as to when to consider
uncopyable object.

Thanks

T.H.

bartek szurgot

unread,
Feb 24, 2012, 11:18:57 AM2/24/12
to
On 02/23/2012 05:45 AM, TH wrote:
> std::vector<HomeForSale> home_vec;
> home_vec.push_back(h1); // need copy constructor??
>
> It sounds like a severe constraints on the possible use of such object, am I missing anything?

in C++11 (new standard of C++) you can also move objects, instead of
copying them:

std::vector<Movable> v;
Movable m;
v.push_back(m); // error - cannot copy
v.push_back( std::move(m) ); // ok - moves object

to learn more read about "rvalue references".

--
pozdrawiam serdecznie / best regards,
bartek szurgot
/* http://www.baszerr.org */

Juha Nieminen

unread,
Feb 25, 2012, 2:10:08 PM2/25/12
to
bartek szurgot <ba...@no.spam> wrote:
> std::vector<Movable> v;
> Movable m;
> v.push_back(m); // error - cannot copy
> v.push_back( std::move(m) ); // ok - moves object

I'm not so sure doing that is such a good "pattern" because after
giving 'm' to the vector you are left with an "empty"/"null" 'm' which
has nothing in it (because what it had was moved to the vector).

A more sensible "pattern" would be to create a temporary that gets
destroyed immediately after its contents have been moved to the vector,
that is:

v.push_back(Movable());

OTOH, there might be some situations where you need to do it like your
version, for example like:

Movable m;
m.doSomething(abc);
m.doSomethingElse(def);
v.push_back(std::move(m));

However, in this case it might be worthy of consideration to move such
initialization to a function, so you would have something like:

Movable gimmeAMovable()
{
Movable m;
m.doSomething(abc);
m.doSomethingElse(def);
return m;
}
...
v.push_back(gimmeAMovable());

This way you don't end up with an "empty" object from which content has
been moved away.

Ian Collins

unread,
Feb 25, 2012, 2:16:46 PM2/25/12
to
That's why I clearly said "If it is inappropriate or too expensive to
copy a T". Some things shouldn't, or simply can't be copied.

--
Ian Collins

Jorgen Grahn

unread,
Feb 25, 2012, 2:49:38 PM2/25/12
to
I know you did; I just added my view that conceptual uniqueness of
things like a HomeForSale does not make copying "inappropriate"
enough.

Pavel

unread,
Feb 25, 2012, 5:45:02 PM2/25/12
to
Juha Nieminen wrote:
> bartek szurgot<ba...@no.spam> wrote:
>> std::vector<Movable> v;
>> Movable m;
>> v.push_back(m); // error - cannot copy
>> v.push_back( std::move(m) ); // ok - moves object
>
> I'm not so sure doing that is such a good "pattern" because after
> giving 'm' to the vector you are left with an "empty"/"null" 'm' which
> has nothing in it (because what it had was moved to the vector).
>
> A more sensible "pattern" would be to create a temporary that gets
> destroyed immediately after its contents have been moved to the vector,
> that is:
>
> v.push_back(Movable());
They've got this, too, in C++11 (some useful new stuff for a change):

v.emplace(v.end(), EmplaceConstructible());
...

HTH
-Pavel

Juha Nieminen

unread,
Feb 26, 2012, 4:38:05 AM2/26/12
to
Pavel <pauldont...@removeyourself.dontspam.yahoo> wrote:
> v.emplace(v.end(), EmplaceConstructible());

Doesn't that call the copy constructor of EmplaceConstructible (which
kind of defeats the whole idea of having a non-copyable class)?

If I understand the documentation correctly, if you wanted to insert
a default-constructed element you would do it like:

v.emplace(v.end());

and if you wanted to give the constructor parameters, you simply give
them as parameters to emplace(), like:

v.emplace(v.end(), 1, 2, 3);

(Perfect forwarding rulez.)

Juha Nieminen

unread,
Feb 26, 2012, 4:42:16 AM2/26/12
to
Juha Nieminen <nos...@thanks.invalid> wrote:
> v.emplace(v.end());

Of, if you are adding it to the end anyways, then:

v.emplace_back();

none Yannick Tremblay

unread,
Feb 27, 2012, 9:32:02 AM2/27/12
to
In article <slrnjkieqh.1...@frailea.sa.invalid>,
I am quite willing to agree with the idea that conceptual uniqueness
may not necessarily require to actually make the object non-copyable.
If there's really a need for the object to be copied, then by all
mean, go for it and figure out a different way to preserve uniqueness.

I am however concerned with the statement "go crazy with smart
pointer". Are you suggesting that:

std::vector< std::shared_ptr<HomeForSale> > home_vec;

is going crazy?

Yannick

Jorgen Grahn

unread,
Feb 27, 2012, 10:54:20 AM2/27/12
to
On Mon, 2012-02-27, yatremblay@bel1lin202.(none) (Yannick Tremblay) wrote:
> In article <slrnjkieqh.1...@frailea.sa.invalid>,
> Jorgen Grahn <grahn...@snipabacken.se> wrote:
>>On Sat, 2012-02-25, Ian Collins wrote:
>>> On 02/23/12 09:47 PM, Jorgen Grahn wrote:
...
>>>> It should be added though, that the uniqueness of a HomeForSale is not
>>>> enough reason to go crazy with smart pointers. If I saw a need to
>>>> place such a thing in a std::vector, I wouldn't hesitate to make it
>>>> copyable. I would also (reluctantly) add a default constructor if
>>>> needed, even though it means introducing "the nil home for sale".
>>>
>>> That's why I clearly said "If it is inappropriate or too expensive to
>>> copy a T". Some things shouldn't, or simply can't be copied.
>>
>>I know you did; I just added my view that conceptual uniqueness of
>>things like a HomeForSale does not make copying "inappropriate"
>>enough.
>
> I am quite willing to agree with the idea that conceptual uniqueness
> may not necessarily require to actually make the object non-copyable.
> If there's really a need for the object to be copied, then by all
> mean, go for it and figure out a different way to preserve uniqueness.
>
> I am however concerned with the statement "go crazy with smart
> pointer". Are you suggesting that:
>
> std::vector< std::shared_ptr<HomeForSale> > home_vec;
>
> is going crazy?

How could I tell without context?

I'm just saying that if std::vector is the only reason to add a
default constructor and copy constructor to HomeForSale, then I curse
under my breath, and then find a way to implement and document them.
I wouldn't want to see any kind of pointer used /just to avoid that/.

none Yannick Tremblay

unread,
Feb 27, 2012, 11:15:40 AM2/27/12
to
In article <slrnjkn9pb.1...@frailea.sa.invalid>,
I still don't follow you.

We have the HomeForSale class. It is non-sensical to copy a
HomeForSale and the concept a a default HomeForSale is also
non-sensical (we don't live in dark utopia of default homes :-)

But /just to avoid using any kind of pointers/, you find a way to
implement copying and default construction that you then need to
document to explain to future generation that they should never be
used per se and that they are only a hack to fullfill the std::vector
requirements...

Why is using "any kind of pointer" such a bad thing that it is worth
jumping through hoop to avoid doing it?

Yannick

Jorgen Grahn

unread,
Feb 27, 2012, 3:58:05 PM2/27/12
to
That's right. I assume most people do it that way.
(If most people here don't, I'd like to hear about it!)

> Why is using "any kind of pointer" such a bad thing that it is worth
> jumping through hoop to avoid doing it?

I don't enjoy doing it, but "jumping through hoops" is overstating the
problem.

Performance, convoluted syntax, manual memory management. Probably
many other reasons too which I haven't thought of because I haven't
encountered those problems.

I'm also not sure that I'd prefer finding a null pointer in my array,
compared to finding a nil HomeForSale.

/Jorgen

PS. I'm talking C++98 here. If any new C++11 features help here, I
haven't checked them out yet.

Ian Collins

unread,
Feb 27, 2012, 11:18:12 PM2/27/12
to
On 02/28/12 09:58 AM, Jorgen Grahn wrote:
> On Mon, 2012-02-27, yatremblay@bel1lin202.(none) (Yannick Tremblay) wrote:
>>
>> We have the HomeForSale class. It is non-sensical to copy a
>> HomeForSale and the concept a a default HomeForSale is also
>> non-sensical (we don't live in dark utopia of default homes :-)
>>
>> But /just to avoid using any kind of pointers/, you find a way to
>> implement copying and default construction that you then need to
>> document to explain to future generation that they should never be
>> used per se and that they are only a hack to fullfill the std::vector
>> requirements...
>
> That's right. I assume most people do it that way.
> (If most people here don't, I'd like to hear about it!)

Well I wouldn't. I hardly ever store Ts in a vector. More often than
not I use a container of shared_ptr<T>. Adding a copy constructor when
your class design doesn't warrant one is poor form. Consider what will
happen if you later need to add a reference member or a managed resource
to your class.

>> Why is using "any kind of pointer" such a bad thing that it is worth
>> jumping through hoop to avoid doing it?
>
> I don't enjoy doing it, but "jumping through hoops" is overstating the
> problem.
>
> Performance, convoluted syntax, manual memory management. Probably
> many other reasons too which I haven't thought of because I haven't
> encountered those problems.
>
> I'm also not sure that I'd prefer finding a null pointer in my array,
> compared to finding a nil HomeForSale.

Using shared_ptr<T> removes most of those issues.

--
Ian Collins

Pavel

unread,
Feb 27, 2012, 11:23:08 PM2/27/12
to
Juha Nieminen wrote:
> Pavel<pauldont...@removeyourself.dontspam.yahoo> wrote:
>> v.emplace(v.end(), EmplaceConstructible());
>
> Doesn't that call the copy constructor of EmplaceConstructible (which
> kind of defeats the whole idea of having a non-copyable class)?
True, that was the wrong syntax.

>
> If I understand the documentation correctly, if you wanted to insert
> a default-constructed element you would do it like:
>
> v.emplace(v.end());
>
> and if you wanted to give the constructor parameters, you simply give
> them as parameters to emplace(), like:
>
> v.emplace(v.end(), 1, 2, 3);
>
> (Perfect forwarding rulez.)

-Pavel

Pavel

unread,
Feb 28, 2012, 12:00:16 AM2/28/12
to
Ian Collins wrote:
> On 02/28/12 09:58 AM, Jorgen Grahn wrote:
>> On Mon, 2012-02-27, yatremblay@bel1lin202.(none) (Yannick Tremblay) wrote:
>>>
>>> We have the HomeForSale class. It is non-sensical to copy a
>>> HomeForSale and the concept a a default HomeForSale is also
>>> non-sensical (we don't live in dark utopia of default homes :-)
>>>
>>> But /just to avoid using any kind of pointers/, you find a way to
>>> implement copying and default construction that you then need to
>>> document to explain to future generation that they should never be
>>> used per se and that they are only a hack to fullfill the std::vector
>>> requirements...
>>
>> That's right. I assume most people do it that way.
>> (If most people here don't, I'd like to hear about it!)
>
> Well I wouldn't. I hardly ever store Ts in a vector. More often than not I use a
> container of shared_ptr<T>. Adding a copy constructor when your class design
> doesn't warrant one is poor form. Consider what will happen if you later need to
> add a reference member or a managed resource to your class.

I think this conversation would win from agreeing on some context, namely a
particular reason why you do not need copy constructor. As an example, if all
one needs from an object (in terms of creation/destruction) is to keep a
collection of them in an array and a standalone object is of no value (it's an
often situation in my practice when you need to dispatch messages to processors
and the processors are relatively rarely created/removed so you want to dispatch
in amortized constant time), std::vector comes to mind. Now it's up to you to
decide whether you introduce copy constructor or create a vector of pointers. If
objects are very small (say, these are some stateless policies or policies
thousands of which may share the state) but there are tons of them, vector of
pointers may create a significant waste, even if you use some pool allocator
(because in addition to an object, which is, say 4-8 bytes, you would have to
keep, say, 4-byte pointers in a vector -- this is a meaningful overhead). There
is also an additional indirection cost (which may, in some patterns, almost half
the effective CPU cache size).

Thus, you are facing a tradeoff: add a copy constructor (unnecessary copying in
this case is the only price; and does not seem significant because the objects
are relatively long-living; not much ideology/design purity considerations are
involved either IMHO) vs vector-of-pointers (with its meaningful additional
space and time costs).

Before C++11, I would probably add a copy constructor (in this particular
context). In C++11, emplace() gives you best of two worlds.

There can certainly be other considerations. For example, add some extra
reference to the message-dispatching processors described above ("extra" in a
sense that it is in addition to those kept by message sources (or logical
connections to them)) and you would be happy if you originally chose shared
pointer design.

IMHO, programming is all about applying abstract ideas to a concrete problem;
and the "concrete problem" part of the equation is at least as important as are
the abstract ideas. It often puzzles me when someone starts an argument on which
abstract idea is "better" without first agreeing on a meaningful context to
apply it.

....

-Pavel

Ian Collins

unread,
Feb 28, 2012, 2:09:15 AM2/28/12
to
I agree with all of the above.

Most of the programming I do these days is either XML document
processing or systems work. Both of these usually involve searching,
sorting and manipulating trees of objects. Thus each "Node", even in
its most basic form contains a vector of children and a vector of
attributes. So even though the objects are fairly small, copying them
can be very expensive.

In the case of XML DOM, the interface requires a pointer based solution.
All access and search functions return references to or lists of nodes
with the document.

With filesystem data and meta-data, I often have to present several
different views of the data, which more often than not is some form of
tree. Here containers of T* or shared_ptr<T> are the logical choice.

So I frequently use the PIMPL idiom, where the "Node" class extends
shared_ptr with the member functions required by the object.

> Thus, you are facing a tradeoff: add a copy constructor (unnecessary copying in
> this case is the only price; and does not seem significant because the objects
> are relatively long-living; not much ideology/design purity considerations are
> involved either IMHO) vs vector-of-pointers (with its meaningful additional
> space and time costs).

Don't forget there are often simple objects (say wrapper round a file
handle) that are simply inappropriate to copy.

> Before C++11, I would probably add a copy constructor (in this particular
> context). In C++11, emplace() gives you best of two worlds.

I don't think id would be appropriate for object were copying is
inappropriate, or objects that hold containers to other objects.

> There can certainly be other considerations. For example, add some extra
> reference to the message-dispatching processors described above ("extra" in a
> sense that it is in addition to those kept by message sources (or logical
> connections to them)) and you would be happy if you originally chose shared
> pointer design.
>
> IMHO, programming is all about applying abstract ideas to a concrete problem;
> and the "concrete problem" part of the equation is at least as important as are
> the abstract ideas. It often puzzles me when someone starts an argument on which
> abstract idea is "better" without first agreeing on a meaningful context to
> apply it.

Very true. When dealing with physical entities, copying them often
isn't appropriate

--
Ian Collins

Jorgen Grahn

unread,
Feb 28, 2012, 4:19:59 PM2/28/12
to
On Tue, 2012-02-28, Pavel wrote:
> Ian Collins wrote:
>> On 02/28/12 09:58 AM, Jorgen Grahn wrote:
>>> On Mon, 2012-02-27, yatremblay@bel1lin202.(none) (Yannick Tremblay) wrote:
>>>>
>>>> We have the HomeForSale class. It is non-sensical to copy a
>>>> HomeForSale and the concept a a default HomeForSale is also
>>>> non-sensical (we don't live in dark utopia of default homes :-)
>>>>
>>>> But /just to avoid using any kind of pointers/, you find a way to
>>>> implement copying and default construction that you then need to
>>>> document to explain to future generation that they should never be
>>>> used per se and that they are only a hack to fullfill the std::vector
>>>> requirements...
>>>
>>> That's right. I assume most people do it that way.
>>> (If most people here don't, I'd like to hear about it!)
>>
>> Well I wouldn't. I hardly ever store Ts in a vector. More often than not I use a
>> container of shared_ptr<T>. Adding a copy constructor when your class design
>> doesn't warrant one is poor form. Consider what will happen if you later need to
>> add a reference member or a managed resource to your class.
>
> I think this conversation would win from agreeing on some context, namely a
> particular reason why you do not need copy constructor.

I think the discussion shifted subtly and because of that became less
understandable. I don't mind keeping the default copy constructor for
things which are naturally copyable. The default constructor was, to me,
the real issue here.

...
> IMHO, programming is all about applying abstract ideas to a concrete problem;
> and the "concrete problem" part of the equation is at least as important as are
> the abstract ideas. It often puzzles me when someone starts an argument on which
> abstract idea is "better" without first agreeing on a meaningful context to
> apply it.

I don't think that was the case here. The HomeForSale example was
concrete enough -- and I don't think anyone suggested you should
/always/ or /never/ use containers of pointers, no matter what the
actual problem is.

/Jorgen

Jorgen Grahn

unread,
Feb 28, 2012, 5:02:08 PM2/28/12
to
On Tue, 2012-02-28, Ian Collins wrote:
> On 02/28/12 09:58 AM, Jorgen Grahn wrote:
>> On Mon, 2012-02-27, yatremblay@bel1lin202.(none) (Yannick Tremblay) wrote:
>>>
>>> We have the HomeForSale class. It is non-sensical to copy a
>>> HomeForSale and the concept a a default HomeForSale is also
>>> non-sensical (we don't live in dark utopia of default homes :-)
>>>
>>> But /just to avoid using any kind of pointers/, you find a way to
>>> implement copying and default construction that you then need to
>>> document to explain to future generation that they should never be
>>> used per se and that they are only a hack to fullfill the std::vector
>>> requirements...
>>
>> That's right. I assume most people do it that way.
>> (If most people here don't, I'd like to hear about it!)
>
> Well I wouldn't. I hardly ever store Ts in a vector. More often than
> not I use a container of shared_ptr<T>. Adding a copy constructor when
> your class design doesn't warrant one is poor form.

I see now that the rest of the posters in the thread focused on the
copy constructor. I got stuck on the default constructor, because
that's where I have problems.

Most of my classes are small, concrete classes and are naturally
copyable. Default copying is enough -- and come to think of it, if the
default wasn't enough, then it would probably not be one of those
classes I'd consider placing in a container!

> Consider what will
> happen if you later need to add a reference member or a managed resource
> to your class.

I consciously try /not/ to think of such things. A future drastic
redesign will simply have to have repercussions. Hopefully it never
has to happen -- the copyability was part of the larger design, not
accidental.

>>> Why is using "any kind of pointer" such a bad thing that it is worth
>>> jumping through hoop to avoid doing it?
>>
>> I don't enjoy doing it, but "jumping through hoops" is overstating the
>> problem.
>>
>> Performance, convoluted syntax, manual memory management. Probably
>> many other reasons too which I haven't thought of because I haven't
>> encountered those problems.
>>
>> I'm also not sure that I'd prefer finding a null pointer in my array,
>> compared to finding a nil HomeForSale.
>
> Using shared_ptr<T> removes most of those issues.

I think that last issue is enough for me.

std::Vector<HomeForSale> homes = lots_of_homes();
assert(!homes.empty());
const HomeForSale& home = homes[0];
assert(home.valid());

is not much worse compared to

std::Vector<shared_ptr<HomeForSale> > homes = lots_of_homes();
assert(!homes.empty());
shared_ptr<HomeForSale> home = homes[0];
assert(home.get());

In both cases I cannot statically know that I can pull a valid home
from the non-empty vector.

/Jorgen

Ian Collins

unread,
Feb 28, 2012, 5:15:50 PM2/28/12
to
You could prevent default initialisation of the pointer:

#include <vector>
#include <tr1/memory>

struct X {};

struct Ptr : std::tr1::shared_ptr<X>
{
explicit Ptr( X* x ) : std::tr1::shared_ptr<X>(x) {}

private:
Ptr() {}
};

int main() {
std::vector<Ptr> v(10);
}

Which is quite handy.

--
Ian Collins

88888 Dihedral

unread,
Feb 28, 2012, 8:01:04 PM2/28/12
to
在 2012年2月26日星期日UTC+8上午3时10分08秒,Juha Nieminen写道:
在 2012年2月26日星期日UTC+8上午3时10分08秒,Juha Nieminen写道:
> bartek szurgot <ba...@no.spam> wrote:
> > std::vector<Movable> v;
> > Movable m;
> > v.push_back(m); // error - cannot copy
> > v.push_back( std::move(m) ); // ok - moves object
>
> I'm not so sure doing that is such a good "pattern" because after
> giving 'm' to the vector you are left with an "empty"/"null" 'm' which
> has nothing in it (because what it had was moved to the vector).
>
> A more sensible "pattern" would be to create a temporary that gets
> destroyed immediately after its contents have been moved to the vector,
> that is:
>
> v.push_back(Movable());
>
> OTOH, there might be some situations where you need to do it like your
> version, for example like:
>
> Movable m;
> m.doSomething(abc);
> m.doSomethingElse(def);
> v.push_back(std::move(m));

I think here the index of the moved m in v should be saved in the next line. But it is possible that the vector v is used as a stack of the same type of objects.



Pavel

unread,
Mar 4, 2012, 1:05:37 AM3/4/12
to
Maybe I am wrong but it seemed to me that Ian defended that "never" position.

His example with file descriptor as a simple object is very close to valid case
for this position (in theory, file handle wrappers can be copied if file
descriptor is dup()ed in copy constructor and dup()-ing is relatively
inexpensive on *NIX but I am not sure about other systems (Windows
DublicateHandle and WSADuplicateSocket in particular; also, that "relative" is
also relative..).

If in a context of a particular problem both correct and practical definition of
copying is *impossible* (as opposed to being just non-sensical for anything but
storing an object in a vector), "never" position can be justified. I think Ian
had that *practically impossible* problem in mind whereas your HomeForSale was
to illustrate a "nonsensical for anything but" case but please correct me if I
am wrong.

-Pavel

88888 Dihedral

unread,
Mar 4, 2012, 9:01:37 PM3/4/12
to
Well, C and C++ are both imperative. But for those objects frozen,
a pointer or reference is enough to read the frozen object.

Thus, I distingush objects that could be modified by some methods in the run-time from those frozen ones that could be referenced by a pointer or a reference.

0 new messages