Michael IV
Michael IV

Reputation: 11424

Disable implicit object copy selecively

I have the following API design problem,or rather dilemma.I seek a way to store some objects in STL vector as object.Yes,I look for a way to increase vector traversing performance through cache locality improvement. Now, the thing is, that type of object should also be exposed as non-copiable to the user of the API. And I mean implicit copy via copy constructor or assignment. But as you surely know, doing something like this:

#define PREVENT_COPY(TypeName)      \
  TypeName (const TypeName &);      \
  void operator= (const TypeName &);
#endif

class FooClass 
{
PREVENT_COPY(FooClass)
public:
  FooClass() {}
 ~FooClass() {}
};

And then:

 int main(int argc,char* argv[])
 {
     std::vector<FooClass> fooVec;
 }

Won't work, because the vector requires access to copy constructor.So ideally,I would want to enjoy both worlds,that's being able to prevent public access to copy/assignment mechanism while still being able to push objects into vector. C array can replace STL vector.But is there a hack to get it working also with std::vector in such a scenario?

As a side note: The reason why I need to disable implicit copy for that type of object is that it's created and managed by an internal system,which is responsible for the whole life cycle of objects of that type.And currently I cache those in a vector of pointers.The target are mobile platforms and the app is real time rendering system.I want to minimize dynamic allocations and improve cache locality for frequently traversed vectors of performance critical data.

Upvotes: 3

Views: 227

Answers (2)

qua
qua

Reputation: 53

The elements of a vector are stored contiguously in the memory. The thing you want to achieve is push separate objects placed in memory into a vector. You can move an object into a vector using std::vector::emplace_back by using its move constructor (by default). However all pointers pointing at that object will be invalid.

In my opinion using a pool like structure and creating your objects beforehand is a better approach in your case.

Upvotes: 0

paddy
paddy

Reputation: 63471

This is exactly what rvalue references (introduced in C++11) are for. If you wish to have a single non-copyable instance that you transfer from one place to the other, you can use move-semantics along with std::vector::emplace_back.

For example:

#include <iostream>
#include <vector>

struct Foo
{
    Foo( int b ) : bar(b) {}

    Foo( const Foo& ) = delete;
    Foo& operator=( const Foo& ) = delete;

    ~Foo() = default;
    Foo( Foo&& f ) = default;
    Foo & operator=( Foo && ) = default;

    int bar;
};


int main()
{
    std::vector<Foo> foos;
    foos.emplace_back( Foo(4) );
    Foo f(2);
    foos.emplace_back( std::move( f ) );
    // Now the contents of 'f' must be considered invalid, and
    // using 'f' is undefined behavior.

    for( const Foo & f : foos )
    {
        std::cout << f.bar << std::endl;
    }
    return 0;
}

Output:

4
2

This is a naive example because it's using trivial data types and defaulted move-construction. But hopefully you get the picture.

Upvotes: 4

Related Questions