Disable implicit object copy

I have the following API design problem, or rather a dilemma. I am looking for a way to store some objects in an STL vector as object.Yes, I am looking for a way to increase the speed at which the vector travels through improving cache locality . Now the point is that this type of object must also be exposed as not usable to the API user. And I mean implicit copying via constructor or copy assignment. But, as you know for sure, do 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;
 }

      

Will not work because it requires access to the copy constructor . Ideally I would like to enjoy both worlds, being able to prevent the public from accessing the copy / assignment mechanism, while still being able to push objects into a vector. C can replace STL vector. But are there any hacks to make it work with std :: vector in a scenario like this?

As a side note: The reason I need to disable implicit copy for this type of object is because it is created and managed by an internal system that is responsible for the entire life cycle of objects of this type. And I am currently caching them in a pointer vector. The target is mobile platforms and the app is a real-time rendering system. I want to minimize dynamic allocations and improve cache locality for frequently moved vectors of critical data.

+3


source to share


2 answers


This is exactly what rvalue references (introduced in C ++ 11) are all about. If you want to have one non-copyable instance that you move from one place to another, 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 since it uses trivial data types and the default move-construction. But hopefully you get the picture.

+4


source


Vector elements are stored contiguous in memory. What you want to achieve is to insert individual objects placed in memory into a vector. You can move an object into a vector using std::vector::emplace_back

using its move constructor (default). However, all pointers pointing to this object will be invalid.



In my opinion, using your pool as a struct and creating your objects is the best approach in your case.

0


source







All Articles