2

我创建了一个类来封装 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 会移动。但是在某些情况下我需要复制。我也可以只保留矢量,因为我知道要保留多少纹理。这两种解决方案的问题是我不知道我可能还有什么其他情况,我希望移动语义能够正常工作。

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

(我使用的是 GCC 4.7)

[编辑]

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

4

1 回答 1

0

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

更多关于这里编译器用来决定移动操作是否安全的标准是什么?

于 2013-05-17T16:13:09.970 回答