C++安全方便高效地复制对象数组
在C++中,我们经常遇到需要对一个对象数组进行复制,比如下面一个结构:
1struct STest
2{
3 int a;
4 int b;
5 vector<int> vctInt;
6};```
7
8
9
10
11我们定义了两个数组:
12
13```cpp
14STest A[20];
15STest B[20];```
16
17
18需要将数组A中的所有内容复制到B数组中,通常我们的做法都是这样:
19
20
21
22```cpp
23for(size_t i = 0; i < ARRAYSIZE(A); ++i)
24{
25 A[i] = B[i];
26}```
27
28
29这里不能直接使用memcpy,因为STest中有vector类型。但是,如果我们定义的是内置类型的数组,则上面的代码效率较低,而直接使用memcpy会更高效。
30
31
32
33为了解决上面的问题,我们可以使用C++模板对不同的类型进行不同的处理。下面有两种写法:
34
35第一种写法是最容易想到的,就是直接写一个模板,并对这个模板的C++内置类型进行特化处理:
36
37
38
39```cpp
40template<typename T,size_t N>
41inline void ArrayAssign(T (&A)[N], T (&B)[N])
42{
43 for(size_t i = 0; i < N; ++i)
44 A[i] = B[i];
45}
46
47template<size_t N>
48inline void ArrayAssign(bool (&A)[N], bool (&B)[N])
49{
50 memcpy(A,B,sizeof(A));
51}
52
53template<size_t N>
54inline void ArrayAssign(char (&A)[N], char (&B)[N])
55{
56 memcpy(A,B,sizeof(A));
57}
58
59template<size_t N>
60inline void ArrayAssign(short (&A)[N], short (&B)[N])
61{
62 memcpy(A,B,sizeof(A));
63}
64
65template<size_t N>
66inline void ArrayAssign(int (&A)[N], int (&B)[N])
67{
68 memcpy(A,B,sizeof(A));
69}
70
71template<size_t N>
72inline void ArrayAssign(long long (&A)[N], long long (&B)[N])
73{
74 memcpy(A,B,sizeof(A));
75}
76
77template<size_t N>
78inline void ArrayAssign(unsigned char (&A)[N], unsigned char (&B)[N])
79{
80 memcpy(A,B,sizeof(A));
81}
82
83template<size_t N>
84inline void ArrayAssign(unsigned short (&A)[N], unsigned short (&B)[N])
85{
86 memcpy(A,B,sizeof(A));
87}
88
89template<size_t N>
90inline void ArrayAssign(unsigned int (&A)[N], unsigned int (&B)[N])
91{
92 memcpy(A,B,sizeof(A));
93}
94
95template<size_t N>
96inline void ArrayAssign(unsigned long long (&A)[N],unsigned long long (&B)[N])
97{
98 memcpy(A,B,sizeof(A));
99}
下面是第二种写法,这种写法,把内置类型的判断提出来,可以方便其它地方使用:
1template<bool A,typename B,typename C>
2struct _if{};
3
4template<typename B,typename C>
5struct _if<true,B,C>{ typedef B Type; };
6
7template<typename B,typename C>
8struct _if<false,B,C>{ typedef C Type; };
9
10template<typename T,size_t N>
11inline size_t ARRAYSIZE(T (&)[N])
12{
13 return N;
14}
15
16template<typename T>
17struct IsInnerType { static const bool Value = false; };
18
19template<>
20struct IsInnerType<bool> { static const bool Value = true; };
21template<>
22struct IsInnerType<char> { static const bool Value = true; };
23template<>
24struct IsInnerType<short> { static const bool Value = true; };
25template<>
26struct IsInnerType<int> { static const bool Value = true; };
27template<>
28struct IsInnerType<long long> { static const bool Value = true; };
29template<>
30struct IsInnerType<unsigned char> { static const bool Value = true; };
31template<>
32struct IsInnerType<unsigned short> { static const bool Value = true; };
33template<>
34struct IsInnerType<unsigned int> { static const bool Value = true; };
35template<>
36struct IsInnerType<unsigned long long> { static const bool Value = true; };
37
38template<typename T,size_t N>
39struct ArrayAssignInnerType
40{
41 static inline void Invoke(T (&A)[N], T (&B)[N])
42 {
43 memcpy(A,B,sizeof(A));
44 }
45};
46
47template<typename T,size_t N>
48struct ArrayAssignCustomType
49{
50 static inline void Invoke(T (&A)[N], T (&B)[N])
51 {
52 for(size_t i = 0; i < N; ++i)
53 A[i] = B[i];
54 }
55};
56
57template<typename T,size_t N>
58inline void ArrayAssign(T (&A)[N], T (&B)[N])
59{
60 _if<IsInnerType<T>::Value,ArrayAssignInnerType<T,N>,ArrayAssignCustomType<T,N> >::Type::Invoke(A,B);
61}
经过上面的处理,我们可以不用担心效率问题;同时,写起来也方便很多,而且不会出错。直接按如下写就OK了:
1ArrayAssign(B,A);```
2
3
4以上代码在VC和GCC下编译通过。
5
6
7
8
- 原文作者:Witton
- 原文链接:https://wittonbell.github.io/posts/2013/2013-05-05-C++安全方便高效地复制对象数组/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议. 进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。