class Color
{
private:
union Data
{
unsigned int intValue;
unsigned char argbBytes[4];
}
private:
Data m_data;
};
另一种方法当然是将数据定义为整数,每当需要时将其转换为字符数组。
我想知道哪种方法更受欢迎。这里的矛盾在于我有一个人提醒我不再使用 union,但在这种情况下它似乎是一种更清晰的解决方案。
class Color
{
private:
union Data
{
unsigned int intValue;
unsigned char argbBytes[4];
}
private:
Data m_data;
};
另一种方法当然是将数据定义为整数,每当需要时将其转换为字符数组。
我想知道哪种方法更受欢迎。这里的矛盾在于我有一个人提醒我不再使用 union,但在这种情况下它似乎是一种更清晰的解决方案。
只要你谨慎使用,联合体可以很好地发挥作用。
它们可以用于两种方式:
允许以多种方式访问单个数据类型(例如,访问颜色作为int或四个char)
创建多态类型(一个值可以容纳整型或浮点型等不同数据类型)
情况(1)是可以的,因为你没有改变类型的含义——你可以读写联合体中的任何成员而不破坏任何内容。这使得以稍微不同的形式访问相同数据的方式非常方便和高效。
情况(2)可能有用,但极其危险,因为您需要始终从联合体内部访问正确类型的数据。如果您将一个int写入并尝试将其作为float读回,则会获得无意义的值。除非内存使用是您主要考虑的因素,否则最好使用一个具有两个成员的简单结构体。
在C语言中,联合体曾经是至关重要的。在C ++中,通常有更好的方法实现相同的目的(例如,类可用于包装一个值并允许以不同方式访问它)。但是,如果需要原始性能或存在关键的内存情况,则联合体仍然可能是一种有用的方法。
这是一种好的实践吗?是的,但有一些要注意的地方。
在内存稀缺的早期,联合体很受欢迎,用于重复使用内存。那些日子已经过去了,使用联合体来实现这个目的会增加不必要的复杂性。不要这样做。
如果一个联合体真正描述了您的数据,就像您所给出的示例一样,那么这是完全合理的。然而,请注意,您正在构建一些平台依赖性。在具有不同整数大小或不同字节顺序的不同平台上,您可能无法得到您所期望的结果。
在C++中,联合体的使用受制于其成员必须是POD(普通旧数据)的限制。例如,联合体成员不能有构造函数或析构函数等其他限制。
std :: string
的示例。 - M.Mvoid *
很难处理就好了 :) class some_xml_class {
public:
void set_property(const string&, const string&);
void set_property(const string&, const vector<string>&);
void set_property(const string&, const set<string>&);
void set_property(const string&, int);
void set_super_property(const string&, const string&);
void set_super_property(const string&, const vector<string>&);
void set_super_property(const string&, const set<string>&);
void set_super_property(const string&, int);
诗歌
class some_xml_class {
public:
typedef boost::variant<string, vector<string>, set<string>, int> property_type;
void set_property(const string&, const property_type&);
void set_super_property(const string&, const property_type&);
仍然可以使用联合体作为一种可接受的做法。只需将rgbBytes更改为数组即可:)
在C中,联���体可用于不同的目的。有时它们被用作变体类型,即在相同的内存位置上保存不同类型的值。在C++中这样的使用方式是值得质疑的,因为你会使用继承/多态性。然而,联合体的另一种用途是为相同数据提供不同的“接口”。这种使用方式对于C++仍然是有效的。
由于您正在使用C ++,我认为这不是一个好的实践。如果您只能使用纯C,当然可以。
在我看来,最大的问题是联合体的大小始终是最大“成员”的大小,因此如果您想存储一个字节或大量数据,则大小为sizeof(shitloadofdata)而不是一个字节。
多态性比联合体更好。
请记住,C++11标准规定使用是未定义行为,请参见M.M的答案(在我看来这是最好的答案)。未来的标准可能会定义它,但多字节数字仍然可以以大端或小端方式存储。因此,如果可移植性是一个问题,您不应该使用联合体或类型转换进行类型切换。
如果这不是问题,让我尝试升级您的代码,以展示联合体如何在C++中发挥作用。
class Color {
union {
uint32_t value;
struct {
uint8_t b, g, r; // LSB value expected
} part;
} data;
public:
uint32_t &value;
uint8_t &r, &g, &b;
Color()
: value(data.value)
, r(data.part.r)
, g(data.part.g)
, b(data.part.b)
{ value = 0; }
Color(Color const& c) : Color() { value = c.value; }
Color(uint32_t _value) : Color() { value = _value; }
Color& operator=(Color const& c) { value = c.value;}
Color& operator=(uint32_t _value) { value = _value;}
};
说明
用法
Color c1 = 0xAABBCC; // implicit call
std::cout << hex << +c1.r << endl; // AA
Color c2 = c1; // copy constructor
c2.g = 127;
std::cout << hex << +c1.g << " " << +c2.g << endl; // BB 7F
c1 = 0xDEADCD; // assignment operator
std::cout << hex << +c1.g << " " << +c2.g << endl; // AD 7F
class Color
{
private:
union
{
unsigned int intValue;
unsigned char argbBytes[4];
};
public:
unsigned int GetIntValue() { return intValue; }
};
union
{
unsigned int intValue;
struct
{
unsigned char r, b, g, a;
};
};
- Niki Yoshiuchi