Re: [问题] 介于static和private的宣告?

楼主: Caesar08 (Caesar)   2015-12-30 12:09:31
※ 引述《noodleT (面T)》之铭言:
class objB{
//变换矩阵
double transform[16];
//上一次的矩阵值
double preTranform[16];
//原始座标
double vertex[3n];
//新座标
double newVertex[3n];
//
void multi(double *matrx)
{
将变换矩阵乘上 matrx
}
double* GetNewVertex()
{
如果变换矩阵值没变
(等于preTransform),
回传newVertex;
否则重算并回传newVertex
}
}
像上面这种情况,
preTransform 和 newVertex
也是只在一个func中使用,
而且原本成员就有类似的名称
transform 和 vertex
→ noodleT: 其他开发者,万一在class中直接使用newvertex,而不是透 12/30 00:05
→ noodleT: 过getnewvertex(),那他所计算的值就不保証是最新的座标 12/30 00:05
以这情况来说,你需要的是mutable
1.GetNewVertex()本身的概念是const的,所以应该加上const
2.return value应该是const double*
3.一旦有呼叫multi(double *matrx)这个function,GetNewVertex()就需要重算
考虑到double的比较问题(见十三诫),如果preTranform"只是"拿来判断transform是否有改变,那我认为用个bool flag来表示是否需要重新计算会比较好
4.承上,flag的初始值要是false
5.
void multi(double *matrx)
{
//do something
flag=false;
}
6.
const double* GetNewVertex() const
{
if(!flag)
calc_newVertex();
return newVertex;
}
7.calc_newVertex()当然本身也是const,然而一个const function想要改变一个data member,就必须要将该data member变为mutable
因此你的double newVertex[3n]会变成mutable double newVertex[3n]
8.
void calc_newVertex() const
{
//do something
flag=true;
}
9.承上,既然如此,flag也要变成mutable
到目前为止,这就满足你的要求,然而,你有mutable,在C++11后会变得有点麻烦
由于calc_newVertex()本身是const,一个const member function本身应该是thread safe的
假设multi(double *matrx)已经被呼叫,之后有多个thread都呼叫calc_newVertex()
你的newVertex会有data race
因此你的newVertex本身需要用std::mutex保护,或是本身变为atomic(flag也是同理,虽然他是bool)
如果选用mutex,会需要额外两个mutex,一个保护flag,一个保护newVertex
(由于会在const member function使用,mutex也要是mutable)
因此我会选择用atomic,把flag改成std::atomic<bool>,newVertex改成atomic<double>
(延伸:flag为什么不用std::atomic_flag而是atomic<bool>呢?)
那你只需要把GetNewVertex()的return value改成const atomic<double>*
到这边为止,就大功告成
你可能还是有疑惑,这样不就多个thread会呼叫calc_newVertex()吗?
答案是对的,因为我不知道这个计算过程到底是大还是小,所以目前能给的建议就是这样
如果你想要只有一个thread去呼叫calc_newVertex(),那你就需要增加mutable std::condition_variable与mutable mutex
再让thread去cv那边wait,直到flag变为false
但我觉得额外使用这些很麻烦,如果只是维持const的基本功能,以上提到的这些就够
除非你真的那么在意效能,或是calc_newVertex()的计算量真的很大
作者: noodleT (面T)   2014-12-30 00:05:00
其他开发者,万一在class中直接使用newvertex,而不是透过getnewvertex(),那他所计算的值就不保証是最新的座标感谢,除了原问题还提醒我执行绪的部分。但这样还是无法阻止其他function 直接使用newVertex使用preTransform而不是flag,是为了:平移+100、平移-100后再呼叫GetNewVertex这种情形。若用flag的判断结果会认为需要重新计算
楼主: Caesar08 (Caesar)   2015-12-30 23:01:00
newVertex应该是private才对,怎么会直接使用呢?
作者: noodleT (面T)   2015-12-31 06:34:00
在实作 objB 的其他函式时应该说:其他共同开发者

Links booklink

Contact Us: admin [ a t ] ucptt.com