[C++-sig] copy constructors and multiple instances

Jim Bosch talljimbo at gmail.com
Thu Sep 1 20:11:25 CEST 2011


On 09/01/2011 07:03 AM, Josh Stratton wrote:
> In my particular scene I have a Scene class, which operates as kind of
> a context for my operations and holds all the meshes in the scene.  I
> send my scene down to the python side so import methods will import
> into the containers in the scene object.  For example,
> addMeshFromFile(scene, fileName) which puts the data from the file
> into the scene object.  However, if the scene object isn't be
> returned, it seems I'm just copying the scene object (which might be
> memory expensive), adding the data to the copy, and throwing the copy
> away as I don't return it and it doesn't affect my original scene
> object in C++ that I passed in.  I assume this is a fairly common
> problem and I need to rework my API somehow like providing a more
> robust copy constructor that does a shallow copy of my data
> containers.  Still, I might have to reorganize it so I'm not passing
> my scene to python.  If an object is copied every time, I think that
> might be memory prohibitive.  I'm including my current source from
> github.
>
> // header file handling my scene and it's data
> https://github.com/strattonbrazil/Sunshine/blob/master/src/scene.h
>
> // functions for creating the bindings to python
> https://github.com/strattonbrazil/Sunshine/blob/master/src/python_bindings.cpp
>
> // python file which reads a file and adds it to the scene
> https://github.com/strattonbrazil/Sunshine/blob/master/src/objImporter.py
>
> Do I need to change need to change my copy constructor to do a more
> shallow copy?  Maybe change my internal scene objects to pointers?
> Would this alleviate the memory issue?

A couple of comments:

- I'm a bit confused by your python_bindings.cpp file; did you paste 
together several files?  If not, I've never seen anyone try to define 
more than one module in a single shared library, and I don't it's 
supposed to work.  You can wrap all of your objects in a single Python 
module - the body of a BOOST_PYTHON_MODULE block is just a regular 
function block, so you can include as many calls to class_ (and other 
things) in there as you like.  This might be part of the confusion about 
needing to import modules from one of your earlier emails.

- You shouldn't have to do anything to the copy constructor to make this 
work.  Boost.Python is perfectly happy to pass things by reference or by 
pointer.  It could be that your QSharedPointers are getting in the way 
of this.  What is the signature of Mesh::buildByIndex?  If the Scene is 
passed by QSharedPointer, that might force a copy, because Boost.Python 
only knows how to dereference the pointer, not copy it (in other words, 
it doesn't want to assume it can copy the smart pointer, because some 
smart pointers like auto_ptr can't be copied, so it's making a new 
QSharedPointer from a copy-constructed object).  If you can change it, 
just make it take a Scene by reference - that will almost certainly 
avoid making copies.  Alternately, if you can use boost::shared_ptr 
instead, that will also solve all of your problems.  Unfortunately 
support for non-boost shared pointers isn't great in Boost.Python right now.

- If you really want to ensure Boost.Python doesn't make unnecessary 
copies of Scene, wrap it with:

class_<Scene,QSharedPointer<Scene>,boost::noncopyable>(...)

That will cause things that require copies to produce compiler errors, 
and you can follow those errors to see exactly where the copy is 
required.  It will also keep you from returning Scene objects by value, 
however, but it sounds like that might be desirable.

Jim




More information about the Cplusplus-sig mailing list