错误:表达式必须是可修改的左值
Posted
技术标签:
【中文标题】错误:表达式必须是可修改的左值【英文标题】:Error: Expression must be a modifiable lvalue 【发布时间】:2014-03-11 11:08:47 【问题描述】:当我尝试将值分配给 x_dev、y_dev 和 pearson 时,我在 for 循环中出现了这个错误。据我所知,它们都应该是可修改的。谁能看到我哪里出错了?
class LoopBody
double *const x_data;
double *const y_data;
double const x_mean;
double const y_mean;
double x_dev;
double y_dev;
double pearson;
public:
LoopBody(double *x, double *y, double xmean, double ymean, double xdev, double ydev, double pear)
: x_data(x), y_data(y), x_mean(xmean), y_mean(ymean), x_dev(xdev), y_dev(ydev), pearson(pear)
void operator() (const blocked_range<size_t> &r) const
for(size_t i = r.begin(); i != r.end(); i++)
double x_temp = x_data[i] - x_mean;
double y_temp = y_data[i] - y_mean;
x_dev += x_temp * x_temp;
y_dev += y_temp * y_temp;
pearson += x_temp * y_temp;
;
按照@Bathsheba 的建议,我已经克服了这些问题。然而,当运行 parallel_for 时,操作符会运行,但永远不会进入 for 循环。
这就是我所说的parallel_for:
parallel_for(blocked_range<size_t>(0,n), LoopBody(x, y, x_mean, y_mean, x_dev, y_dev, pearson), auto_partitioner());
【问题讨论】:
【参考方案1】:()
运算符标记为 const
,并且您正在尝试修改类成员数据(例如 x_dev
、y_dev
和 person
)。这是不允许的,这就是您收到编译时错误的原因。
您可能希望从方法中删除 const
。
或者,您可以将要修改的成员数据标记为mutable
,但这不是首选解决方案,因为它会使代码变脆、难以阅读并且可能对多线程造成严重破坏。
【讨论】:
这解决了这个问题,但我现在在编译时遇到错误:c:\program files (x86)\tbb41\include\tbb\parallel_for.h(110): error C3848: expression has type 'const LoopBody' 将丢失一些 const-volatile 限定符,以便调用 'void LoopBody::operator ()(const tbb::blocked_range()
不应该修改类成员数据。为什么你需要这样做?如果你真的需要那么,也许,使类成员mutable
并标记函数const
是前进的方向。但我不喜欢这样,因为我在答案中陈述了原因。
你是绝对正确的()
不应该修改类成员,特别是因为tbb::parallel_for
使用多个主体实例,并且在单个实例中累积的任何内容都将丢失。因此,const
和mutable
的组合只会隐藏真正的问题。正确的解决方案是使用tbb::parallel_reduce
。【参考方案2】:
您似乎想要进行归约,即在数据上计算一些聚合值。
为此,TBB 提供了一个特殊的函数模板:parallel_reduce
。与您现在可能使用的 parallel_for
不同,parallel_reduce
不需要主体类的 operator()
为 const,因为该类的实例会累积部分结果。但是,它对类提出了其他要求:需要有一个特殊的构造函数以及一个方法来合并来自另一个 body 实例的部分结果。
更多信息可以在英特尔(R) TBB 用户指南中找到:http://www.threadingbuildingblocks.org/docs/help/tbb_userguide/parallel_reduce.htm
还有parallel_reduce
的重载,它需要两个函子——一个用于主体,另一个用于合并部分结果——以及用于初始化累加器的特殊“身份”值。但是您一次计算三个聚合值,因此您仍然需要有一个结构或类来将所有三个值存储在一个变量中。
【讨论】:
以上是关于错误:表达式必须是可修改的左值的主要内容,如果未能解决你的问题,请参考以下文章