具有常量成员的结构的默认复制操作
Default Copy Operations for Structs with Constant Members
我有一个 Texture
结构,用于保存纹理的宽度、高度和 ID 号。我还有一个 Loader class,其中包含许多专用于加载内容(例如纹理)的静态函数。当我尝试声明一个未初始化的 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"
我已经用谷歌搜索了一段时间,但找不到任何东西。也许是我不知道要什么Google,我不知道。感谢您的帮助!
其中的几个部分
1.The 默认构造函数不起作用,因为您不能拥有未初始化的 const 对象(即使是基元)。对于您的简单情况,您可能只希望对它们进行值初始化,这很容易实现:
struct Texture {
const unsigned int id{};
const float width{};
const float height{};
//...
};
2.You 不能将隐式生成的 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!
如果您希望能够赋值,则需要使用非常量数据成员。 如果你有 const 成员,你不能使用隐式运算符=*你可以 const_cast
但这会导致未定义的行为,这是一个可怕的想法(只是在有人提到之前说出来它在评论中)。
您不仅仅是在声明tex
,您还在定义它。定义点需要初始化。稍后尝试分配并没有初始化它。
不要使用全局变量。
*除非那些 const 成员有一个 operator=(..) const
但那会很奇怪
Texture
是一个有 const
成员的 aggregate。您必须在初始化期间提供这些值。
当您使用 return 和 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;
}
我有一个 Texture
结构,用于保存纹理的宽度、高度和 ID 号。我还有一个 Loader class,其中包含许多专用于加载内容(例如纹理)的静态函数。当我尝试声明一个未初始化的 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"
我已经用谷歌搜索了一段时间,但找不到任何东西。也许是我不知道要什么Google,我不知道。感谢您的帮助!
其中的几个部分
1.The 默认构造函数不起作用,因为您不能拥有未初始化的 const 对象(即使是基元)。对于您的简单情况,您可能只希望对它们进行值初始化,这很容易实现:
struct Texture {
const unsigned int id{};
const float width{};
const float height{};
//...
};
2.You 不能将隐式生成的 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!
如果您希望能够赋值,则需要使用非常量数据成员。 如果你有 const 成员,你不能使用隐式运算符=*你可以 const_cast
但这会导致未定义的行为,这是一个可怕的想法(只是在有人提到之前说出来它在评论中)。
您不仅仅是在声明tex
,您还在定义它。定义点需要初始化。稍后尝试分配并没有初始化它。
不要使用全局变量。
*除非那些 const 成员有一个 operator=(..) const
但那会很奇怪
Texture
是一个有 const
成员的 aggregate。您必须在初始化期间提供这些值。
当您使用 return 和 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;
}