









请看下面这个对数组操作的表达式:
.x = 1.2*x + x*y (其中x,y都是一维数组类型的实例)
计算机世界中实现这样的操作我们基本需要两个临时变量,一个记录 array*array的中间结果,一个记录 常量*array 的中间结果。如果数组很大的情况下,这样作的效率是很低的。
改进方案一:
temp = x;
temp*=y;
x*= 1.2;
x += temp;
这个解决方案通过拆分表达式只使用了一个临时变量就达到了我们想要的结果。但带来了新的问题:
1。表达式拆分开来,给阅读带来了困难。
2。同样使用了临时变量temp,如果数组很大的情况下,同样存在效率问题。
理想的解决方案是不产生任何临时变量,同时又能够保证该表达式的书写完整性,如下:
for (int i = 0; i < 数组大小;++i)
{
x[i] = 1.2*x[i] + x[i]*y[i];
}
下面给出具体的实现代码(参见 c++ template 关于模版表达式部分)
1
//----------------------------------------------------------------------
2
3
4
//数组类型
5
6
7
template<typename T>
8
class SArray
9
{
10
public:
11
explicit SArray (size_t s)
12
: storage(new T[s]), storage_size(s)
13
{
14
init();
15
}
16
17
SArray (SArray<T> const& orig)
18
: storage(new T[orig.size()]), storage_size(orig.size())
19
{
20
copy(orig);
21
}
22
~SArray()
23
{
24
delete[] storage;
25
}
26
SArray<T>& operator= (SArray<T> const& orig)
27
{
28
if (&orig!=this)
29
{
30
copy(orig);
31
}
32
return *this;
33
}
34
size_t size() const
35
{
36
return storage_size;
37
}
38
T operator[] (size_t idx) const
39
{
40
return storage[idx];
41
}
42
T& operator[] (size_t idx)
43
{
44
return storage[idx];
45
}
46
protected:
47
void init()
48
{
49
for (size_t idx = 0; idx<size(); ++idx)
50
{
51
storage[idx] = T();
52
}
53
}
54
void copy (SArray<T> const& orig)
55
{
56
for (size_t idx = 0; idx<size(); ++idx)
57
{
58
storage[idx] = orig.storage[idx];
59
}
60
}
61
62
private:
63
T* storage;
64
size_t storage_size;
65
};
66
//----------------------------------------------------------------------
67
68
69
//表达式数组类型
70
71
72
73
template <typename T, typename Rep = SArray<T> >
74
class Array
75
{
76
private:
77
Rep expr_rep;
78
public:
79
explicit Array (size_t s)
80
: expr_rep(s)
81
{
82
}
83
Array (Rep const& rb)
84
: expr_rep(rb)
85
{
86
}
87
Array& operator= (Array const& b)
88
{
89
for (size_t idx = 0; idx<b.size(); ++idx)
90
{
91
expr_rep[idx] = b[idx];
92
}
93
return *this;
94
}
95
template<typename T2, typename Rep2>
96
Array& operator= (Array<T2, Rep2> const& b)
97
{
98
for (size_t idx = 0; idx<b.size(); ++idx)
99
{
100
expr_rep[idx] = b[idx];
101
}
102
return *this;
103
}
104
size_t size() const
105
{
106
return expr_rep.size();
107
}
108
T operator[] (size_t idx) const
109
{
110
return expr_rep[idx];
111
}
112
T& operator[] (size_t idx)
113
{
114
return expr_rep[idx];
115
}
116
Rep const& rep() const
117
{
118
return expr_rep;
119
}
120
Rep& rep()
121
{
122
return expr_rep;
123
}
124
};
125
126
//----------------------------------------------------------------------
127
128
129
//数值类型封装
130
131
132
template <typename T>
133
class A_Scalar
134
{
135
private:
136
T const& s;
137
public:
138
A_Scalar (T const& v)
139
: s(v)
140
{
141
}
142
T operator[] (size_t) const
143
{
144
return s;
145
}
146
size_t size() const
147
{
148
return 0;
149
};
150
};
151
152
//----------------------------------------------------------------------
153
154
155
//类型封装定义
156
157
template <typename T>
158
class A_Traits
159
{
160
public:
161
typedef T const& ExprRef;
162
};
163
164
template <typename T>
165
class A_Traits<A_Scalar<T> >
166
{
167
public:
168
typedef A_Scalar<T> ExprRef;
169
};
170
171
//----------------------------------------------------------------------
172
173
174
//表达式封装
175
176
177
template <typename T, typename OP1, typename OP2>
178
class A_Add
179
{
180
private:
181
typename A_Traits<OP1>::ExprRef op1;
182
typename A_Traits<OP2>::ExprRef op2;
183
184
public:
185
A_Add (OP1 const& a, OP2 const& b)
186
: op1(a), op2(b)
187
{
188
}
189
T operator[] (size_t idx) const
190
{
191
return op1[idx] + op2[idx];
192
}
193
size_t size() const
194
{
195
return op1.size()!=0 ? op1.size() : op2.size();
196
}
197
};
198
199
template <typename T, typename OP1, typename OP2>
200
class A_Mult
201
{
202
private:
203
typename A_Traits<OP1>::ExprRef op1;
204
typename A_Traits<OP2>::ExprRef op2;
205
206
public:
207
A_Mult (OP1 const& a, OP2 const& b)
208
: op1(a), op2(b)
209
{
210
}
211
T operator[] (size_t idx) const
212
{
213
return op1[idx] * op2[idx];
214
}
215
size_t size() const
216
{
217
return op1.size()!=0 ? op1.size() : op2.size();
218
}
219
};
220
221
//----------------------------------------------------------------------
222
223
//操作封装
224
225
226
template <typename T, typename R1, typename R2> Array<T,A_Add<T,R1,R2> > operator+ (Array<T,R1> const& a, Array<T,R2> const& b)
227
{
228
return Array<T,A_Add<T,R1,R2> >(A_Add<T,R1,R2>(a.rep(),b.rep()));
229
}
230
template <typename T, typename R1, typename R2>
231
Array<T, A_Mult<T,R1,R2> > operator* (Array<T,R1> const& a, Array<T,R2> const& b)
232
{
233
return Array<T,A_Mult<T,R1,R2> >(A_Mult<T,R1,R2>(a.rep(), b.rep()));
234
}
235
template <typename T, typename R2> Array<T, A_Mult<T,A_Scalar<T>,R2> > operator* (T const& s, Array<T,R2> const& b)
236
{
237
return Array<T,A_Mult<T,A_Scalar<T>,R2> >(A_Mult<T,A_Scalar<T>,R2>(A_Scalar<T>(s), b.rep()));
238
}
239
//----------------------------------------------------------------------
240
241
测试代码如下:
1
2
//----------------------------------------------------------------------
3
//定义,初始化
4
5
Array<double> x(1000), y(1000);
6
for (int i=0; i<1000; ++i)
7
{
8
x[i] = i;
9
y[i] = x[i]+x[i];
10
}
11
12
//----------------------------------------------------------------------
13
14
//使用测试
15
16
std::cout << "x: ";
17
print(x);
18
19
std::cout << "y: ";
20
print(y);
21
22
x = 1.2 * x;
23
std::cout << "x = 1.2 * x: ";
24
print(x);
25
26
x = 1.2*x + x*y;
27
std::cout << "1.2*x + x*y: ";
28
print(x);
29
30
x = y;
31
std::cout << "after x = y: ";
32
print(x);
33
34
//----------------------------------------------------------------------
35
该解决方案分析:
1。表达式的计算延迟到赋值得时候才进行。
2。通过对象编译时封装了表达式信息。
3。利用 trait 技术提供类型封装。
4。效率高,没有任何临时变量的产生。
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。