具有常量成员的结构的默认复制操作

时间:2016-03-31 00:28:23

标签: c++ struct const copy-constructor default-constructor

我有一个Texture结构,用于保存纹理的宽度,高度和ID值。我还有一个Loader类,其中包含许多用于加载内容的静态函数,例如纹理。当我尝试声明未初始化的Texture,然后稍后对其进行初始化时,会出现问题。以下是Texture.h中的代码:

namespace bronze {

struct Texture {
    const unsigned int id;
    const float width;
    const float height;

    Texture() = default;
    Texture(Texture&&) = default;
    Texture& operator=(Texture&&) = default;
};

}

Loader.cpp

Texture(const std::string& file, float scale) {
    unsigned int id;
    float width, height;

    loadTextureUsingExternalLibrary(&id, &width, &height);
    doThingsWithTexture(id);

    return Texture{id, width, height}
}

然后在main.cpp

#include "Loader.h"
#include "Texture.h"

using namespace bronze;

Texture tex;

int main() {
    tex = Loader::loadTexture("asdf.png", 2.f);
    drawTextureOnTheWindowSomehow(tex);
    return 0;
}

以下是我得到的(当然缩短的)错误(MinGW是我的编译器):

error: use of deleted function 'bronze::Texture::Texture()'
Texture tex;

note: 'bronze::Texture::Texture()' is implicitly deleted because the default
definition would be ill-formed:
Texture() = default;

...complains about each member being uninitialized

error: use of deleted function 'bronze::Texture& bronze::Texture::operator=
Bronze::Texture&&)'
tex = Loader::loadTexture("asdf.png", 2.f);

note: 'bronze::Texture& bronze::Texture::operator=(bronze::Texture&&)' is
implicitly deleted because the default definition would be ill-formed:
Texture& operator=(Texture&&) = default;

...complains for each struct member that "non-static const member can't use
default assignment operator"

我一直在谷歌上搜索一段时间,但找不到任何东西。也许是因为我不知道谷歌是什么,我不知道。感谢帮助!

2 个答案:

答案 0 :(得分:2)

本节的几个部分

1.默认构造函数不起作用,因为你没有未初始化的const对象(甚至原语)。对于你的简单情况,你可能只是想让它们进行值初始化,这可以很容易地实现:

struct Texture {
    const unsigned int id{};
    const float width{};
    const float height{};
    //...
};

2.您不能将隐式生成的operator=用于具有const数据成员的对象,因为这需要分配给const对象。

struct A { const int i{}; };
A a1;
A a2(a1); // fine
a1 = a2; // not fine. can't do a1.i = a2.i since a1.i is const!

如果您希望能够分配,则需要使用非常量数据成员。 你不能使用隐式operator =如果你有const成员* 你可以const_cast但是这会导致未定义的行为并且是一个可怕的想法(只是在有人提到它之前说出来)在评论中)。

您不是声明 tex,而是您正在定义它。定义点需要初始化。尝试稍后分配不会初始化它。

不要使用全局变量。

*除非那些const成员有operator=(..) const,但这很奇怪

答案 1 :(得分:0)

Textureaggregateconst成员。您必须在初始化期间提供值。

当您使用return Texture{id, width, height}返回时,它会为您进行聚合初始化,但如果您尝试构造Texture,则构造函数在没有初始化const成员的情况下将无法工作。

所以你可能宁愿使用:

Texture(unsigned int id, float width, float height) : id{id}, width{width}, height{height} {};

另请注意,您可能无法使用隐式删除的operator=,但您可以定义自己的struct Texture { const unsigned int id; const float width; const float height; int other; Texture(unsigned int id,float width,float height,int other) : id{id},width{width},height{height},other{other} {}; Texture(const Texture & rhs) : id{rhs.id},width{rhs.width},height{rhs.height} {}; Texture& operator=(const Texture& rhs) { other = rhs.other; return *this; }; }; int main() { Texture t0{1,2,3,0}; auto t1 = Texture(3,3,3,1); Texture t2 = t0; // t2's constants are initialized to be the same as t0's t2 = t1; // only the non const member data is copied return 0; }

以下程序适用于赋值运算符。

JSON.parse(data)