i'm trying to wrap opengl textures into an RAII based object but I don't know how to handle copying when a RAII object is very expensive to copy.
Here's an example of an expensive RAII object.
class Image {
public:
Image(const Image& other) {
this->pixels = other.pixels;
}
Image& operator=(const Image& rhs) {
this->pixels = rhs.pixels;
}
void push_pixel(uint8_t pixeldata) {
pixels.push_back(pixeldata);
}
private:
std::vector<uint8_t> pixels;
};
When the image object is copied from one to another e.g.
int main(int argc, char** argv) {
Image myimage;
Image newimage;
// Inserting 1 million pixels into the image.
for (uint32_t i = 0; i < 1000000; i ) {
myimage.push_pixel(0);
}
// Copying the image from myimage to newimage.
newimage = myimage;
return 0;
}
Results in an extremely expensive operation, are there are alternatives to this which has the same behaviour?
Thanks.
CodePudding user response:
There are three typical approaches to this problem:
Using move semantics and rule of five
Using C standard shared pointers or shared intrusive pointers
Using copy-on-write
Each of these methods have their own pros and const. Most C developers would implement with (1) move semantics because it is more aligned with the standard and widely available. However move semantics has some extra complexity added to the user's usage, like adding std::move
manually.
By using (2) shared pointers you are not actually copying your image but sharing it. Which means that if you want to modify it then you have to explicitly make a copy of the object.
Copy-on-write (3) is like shared pointers but the copy is handled automatically for you: if you ever try to use a method that is not const, the object will make a copy of it under the hood. This is like std::string was before C 11.