简体   繁体   中英

std::vector resizing using unsafe move when no copy is provided

I made a class to encapsulate some functionality from OpenGL textures, my requirements are pretty simple so I don't need much more than being able to control the texture data and types. My class is the following (simplified):

class Texture
{
    std::vector<unsigned char> _data;
    [...]
    public:
        Texture(std::vector<unsigned char> data, vec2 size, GLint internal_format, GLenum format, GLenum type);
        Texture(const Texture& other)
        {
            //copies the data and creates a new buffer with OpenGL
        }
        Texture(Texture&& other) noexcept
        {
            //moves the data, copies the buffer id and set the old buffer id to 0
        }
}

Now I have another class that manages some textures using a std::vector, in an effort to make most of my memory management automatic I realized that I don't need to allocate these textures in the heap, so the vector type is std::vector<Texture> . The problem is that when I add new textures to the vector it is making copies instead of moving. I found two solutions, if delete the copy constructor/assignment operator, std::vector moves. But I need to copy in some situations. I can also just reserve the vector since I know how many textures I'll be keeping. The problem with both these solutions is that I don't know what other cases I may have and I expect move semantics to work correctly.

I read other other answers about this problem, but using noexcept doesn't solve the problem, and as I said, if delete the copy constructor the move constructor will be chosen. Even if I remove the noexcept and throw something from it. Is this correct? Should the compiler use an unsafe move constructor if there's no copy constructor available? Also, why won't the compiler choose the safe move constructor I'm providing?

(I'm using GCC 4.7)

[edit]

I made an example: http://liveworkspace.org/code/4bzSMD $6 and realized that if I leave the default destructor, then the move constructor will be used, but If I provide a destructor, then it copies. Why is that?

I still don't know why GCC chooses an unsafe move constructor if not copy constructor is provided, but the move problem is from an explicit destructor on GCC 4.7 not being noexcept(true) by default, so when there's a copy available, it will be seen as safer by the compiler (since copying doesn't destroy the element.)

More on that here What is the criteria that the compiler uses to decide if a move operation is safe?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM