当没有提供副本时,std :: vector使用不安全的移动进行大小调整

时间:2013-02-13 06:54:49

标签: c++ move-semantics

我创建了一个类来封装OpenGL纹理中的一些功能,我的要求非常简单,所以我不需要能够控制纹理数据和类型。我的课程如下(简化):

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
        }
}

现在我有另一个使用std :: vector管理一些纹理的类,为了使我的大部分内存管理自动化,我意识到我不需要在堆中分配这些纹理,所以矢量类型是std::vector<Texture>。问题是,当我向矢量添加新纹理时,它正在制作副本而不是移动。我找到了两个解决方案,如果删除了复制构造函数/赋值运算符,std :: vector就会移动。但我需要在某些情况下复制。我也可以保留矢量,因为我知道我将保留多少纹理。这两个解决方案的问题在于我不知道我可能有什么其他情况,我希望移动语义能够正常工作。

我读了关于这个问题的其他other个答案,但使用noexcept并没有解决问题,正如我所说,如果删除复制构造函数,将选择移动构造函数。即使我删除noexcept并从中抛出一些东西。它是否正确?如果没有可用的复制构造函数,编译器是否应该使用不安全的移动构造函数?另外,为什么编译器不会选择我提供的安全移动构造函数?

(我正在使用GCC 4.7)

[编辑]

我做了一个例子:http://liveworkspace.org/code/4bzSMD $ 6 并意识到如果我离开默认的析构函数,那么将使用移动构造函数,但是如果我提供了析构函数,那么它就会复制。那是为什么?

1 个答案:

答案 0 :(得分:0)

我仍然不知道为什么GCC选择不安全的移动构造函数如果没有提供复制构造函数,但移动问题来自GCC 4.7上的显式析构函数,默认情况下不是noexcept(true),所以当&# 39;副本可用,编译器会认为它更安全(因为复制不会破坏元素。)

此处有更多信息What is the criteria that the compiler uses to decide if a move operation is safe?