这是一个新手C ++问题。我正在阅读维基百科中的“功能对象”一文。本文在C ++中有一个类似于以下内容的示例:
struct printClass {
int &count;
printClass(int &n) : count(n) {}
void operator()(int &i) const {
count++;
cout << i << "[" << count << "] ";
}
};
int main(int argc, char** argv) {
vector<int> a(5, 7);
a[4] = -1;
a.resize(10, 3);
int state = 0;
for_each(a.rbegin(), a.rend(), printClass(state));
}
我有两个问题:
当count是常规变量而非引用类型时,为什么编译失败? Demo
为什么编译失败我将ctor
更改为以下内容? Demo
printClass(int &n) { count = n; }
感谢。
编辑:谢谢你的解释。我看到以下版本也有效。是否有理由选择一个而不是另一个?struct printClass {
int count;
printClass(int n) { count = n; }
void operator()(int &i) {
count++;
cout << i << "[" << count << "] ";
}
};
编辑:根据iammilind的回复,这里是使用const_cast<int &>
的第3版。
struct printClass {
int count ;
printClass(int n) : count(n) {}
void operator()(int &i) const {
const_cast<int &>(count)++;
cout << i << "[" << count << "] ";
}
};
答案 0 :(得分:4)
(1)当count是常规变量而不是a时,为什么编译失败 参考类型?
这是一个非常有趣的问题。问题应该是,为什么代码在count
被声明为引用时编译。 :)
常规变量失败,因为int count
在const
限定函数operator()(int &i) const;
内无法修改。
参考文献略有不同。在您的代码中,您将方法声明为const
,这意味着引用count
的{{1}}现在无法引用任何其他内容。
但由于引用的性质,这无论如何都不可能:)。初始化后无法更改引用绑定
i
只是检查您是否正在更改operator()
与其他任何内容的绑定?答案永远不是。因为count
更改了count++
引用的值而不是绑定。
在您的代码中,count
成员方法是否为const
并不重要。
将int& count
与int& count;
相关联,并尝试自行模拟情况。
(2)为什么编译失败我将ctor更改为以下内容?
int* const p_count;
因为初始化时必须将引用赋给变量。在简单的例子中;
CountFrom(int &n) { count = n; }
另外,在int i, &r; // error, because 'r' not initialized
r = i; // this is not initialization but a copy
内处理引用变量时,应格外小心。因为很容易弄乱它们的范围和有效性
例如,class
的有效性取决于count
的范围。
编辑:在第二次编辑之后,了解该版本的工作原理非常简单。
因为i
现在是一个简单的变量。与引用不同,它可以在构造函数的初始化列表中从初始化中跳过
此外count
的{{1}}正确性已消失,因此const
中的任何成员变量现在都可以在其中进行修改。
如果您要声明其中operator()
成员“必须”更改(除非任何变量为class
或您使用,否则您应该选择成员方法的const
版本class
)。在所有其他情况下,使用成员方法的普通版本。它们都可以共存,具体取决于您的业务逻辑。这是一个广泛的问题,为此有另一个线程是值得的。