C/C++:union关键字

发布时间 2023-03-24 18:04:04作者: karinto

1、union内存分布:

union U {
	int x;
	float y;
};
int main()
{
	U u;
	u.x = 123;
	show(u.x);
	u.y = 16.256;
	show(u.x, u.y); //union两个变量共用一块内存, u.x的输出不正确

	return 0;
}

 

2、union短字符串优化

struct short_str {
	union { //匿名union
		unsigned long long hs;
		char s[8];
	};
};

int main()
{
	short_str s;
	memcpy(s.s, "12345", 6);
	show(s.s, s.hs); //通过传入s.s, 输出s.hs, 可以快速地获得短字符串的哈希值

	return 0;
}

 

3、union取别名简化操作

  在二维问题中,我们定义了如下line和point结构体,但访问具体数据就需要操作name.p1.x,较为麻烦。

struct point {
    int x, y;
};
struct line {
    point p1, p2;
};

  同样可以通过union的内存分布特性简化这一操作步骤,将struct point p1, p2和int arr[4]使用union联合起来。

struct point {
	int x, y;
};

struct line {
	union {
		struct {
			point p1, p2;
		};
		int arr[4];
	};
};

int main()
{
        line L = { 123, 456, 789, 1020 };
	show(L.p1.x, L.p1.y, L.p2.x, L.p2.y);
	for (int i = 0; i < 4; i++) { L.arr[i] = i + 567; }
	show(L.p1.x, L.p1.y, L.p2.x, L.p2.y);

	return 0;
}

  

  

4、union实现简单动态类型

struct var {
	union {
		int iv;
		double dv;
		char *sv; //char* sv
	};

	var(const int& v) : iv{ v } {};
	var(const double& v) : dv{ v } {};
	var(const char* s) {
		int len = strlen(s);
		sv = new char[len + 1];
		memcpy(sv, s, len + 1);
	}
};

int main()
{
	var x = 1234;
	show(x.iv);
	x = 3.14;
	show(x.iv, x.dv);
	x = "hello~~~";
	show(x.iv, x.dv, x.sv);

	return 0;
}

  由上例,我们并没有detele掉释放new出的内存,为了避免内存泄漏,我们希望union能做到内存的自动释放,但原生union又不能做到自动析构。

  C++17中引入一个variant ,它可以实现和union类似的效果,并且会自动析构。

 

源代码:

#include <iostream>

using namespace std;

void show() { cout << endl; }

template<typename T, typename... Types>
void show(const T& firstArg, const Types&... args) {
	cout << firstArg << " ";
	show(args...);
}

union U {
	int x;
	float y;
};

struct short_str {
	union { //匿名union
		unsigned long long hs;
		char s[8];
	};
};

struct point {
	int x, y;
};

struct line {
	union {
		struct {
			point p1, p2;
		};
		int arr[4];
	};
};

struct var {
	union {
		int iv;
		double dv;
		char *sv; //char* sv
	};

	var(const int& v) : iv{ v } {};
	var(const double& v) : dv{ v } {};
	var(const char* s) {
		int len = strlen(s);
		sv = new char[len + 1];
		memcpy(sv, s, len + 1);
	}
};

int main()
{
	U u;
	u.x = 123;
	show(u.x);
	u.y = 16.256;
	show(u.x, u.y); //union两个变量共用一块内存, u.x的输出不正确

	short_str s;
	memcpy(s.s, "12345", 6);
	show(s.s, s.hs); //通过传入s.s, 输出s.hs, 可以快速地获得短字符串的哈希值

	line L = { 123, 456, 789, 1020 };
	show(L.p1.x, L.p1.y, L.p2.x, L.p2.y);
	for (int i = 0; i < 4; i++) { L.arr[i] = i + 567; }
	show(L.p1.x, L.p1.y, L.p2.x, L.p2.y);

	var x = 1234;
	show(x.iv);
	x = 3.14;
	show(x.iv, x.dv);
	x = "hello~~~";
	show(x.iv, x.dv, x.sv);

	return 0;
}

  执行结果:

123
1099041866 16.256
12345 14757170307495309873
123 456 789 1020
567 568 569 570
1234
1374389535 3.14
16716512 -9.25596e+61 hello~~~

  

原文:https://zhuanlan.zhihu.com/p/595288133

作者:严格鸽