我正在阅读" C ++编程语言 - 第四版"我正在打一个简单的练习只是为了得到一些C ++语法,我不小心偶然发现了一些令我眉毛的东西。简而言之,我忘了在()
添加accept
in main:
bool accept()
{
cout << "Do you want to proceed (y or n)?\n";
char answer = 0;
cin >> answer;
if (answer == 'y')
{
return true;
}
return false;
}
int main()
{
accept;
}
运行并编译并生成(在VS2015中)
C4551 - 函数调用缺少参数列表
我发现自己正在阅读lambdas和一些关于SO的问题应该被关闭,因为他们主要是要求调试我的代码。&#34;
我认为如果代码编译并运行,并且该函数包含一个阻塞语句(等待用户输入)和一个返回类型,那么所有代码都将按预期执行,而不管是否缺少括号;但事实并非如此。
此外,我想我会将主调用accept
更改为bool a = accept; cout << a;
以尝试阻止任何优化(如果那是实际发生的情况),并且没有调用{ {1}}代码。
我很想知道的是:
accept()
编译进来的调用是什么?accept
中的代码被调用accept
代码会生成bool a = accept; cout << a;
作为输出。当1
是默认的bool值(至少在C#中)并且由于接受代码没有被执行而没有返回真值时,怎么会这样呢?答案 0 :(得分:13)
没有“致电accept
”。见#3。
因为#1。
使用函数名而不使用函数调用语法(即:()
)意味着您正在访问函数本身。例如,您可以将其存储在函数指针中(通过函数到指针衰减):
using my_func = bool(*)(); //Function that takes nothing and returns a bool.
my_func var = accept; //Store a pointer to `accept`.
然后,您可以发出var();
,即accept
。
但是,因为你从不存储函数,编译器猜测你可能想要调用函数,而不是访问函数的指针。 accept;
但是是合法的C ++语句,因此编译器不能对其进行错误。它可以发出警告,因为语句没有任何结果,你可能打算调用该函数。这与1;
这样的陈述没有什么不同:完全合法,但完全没用。
这是因为C ++技巧。非空指针衰减到布尔值true
。并且accept
衰减到非空的函数指针。因此,转换为bool
时,它将为true
。你还没有调用这个功能。
答案 1 :(得分:8)
在C ++中,任何以分号后跟的表达式都是合法的陈述。 (为什么?因为C让你这样做,我想)。这意味着以下所有内容都是法律声明:
5;
3 + 5;
1 % 2 == 0;
此表单语句的效果是表达式被计算然后被丢弃。一个好的优化编译器会消除这里的所有逻辑,因为这些都没有任何副作用。
在你的情况下,写
accept;
是一个法律声明,因为accept
是一个表达式,用于评估函数accept
的引用。这意味着accept;
作为语句意味着&#34;评估accept
的地址,然后丢弃它。&#34;这里没有调用函数的原因是函数名本身并不调用函数;你需要括号(函数调用运算符)来实际调用。例如,如果要将函数传递给另一个函数,这很有用。例如,您可能希望将比较函数传递给std::sort
,如下所示:
std::sort(range.begin(), range.end(), nameOfMyComparisonFunction)
在这里,如果尝试调用nameOfMyComparisonFunction
,那将是一个真正的问题,因为在排序例程开始之前,参数不可知。
那为什么这是警告而不是错误?嗯,它是完全合法的C ++代码,因此编译器无法顺从地将其称为错误。但是,编译器将其标记为警告是正确的,因为它几乎肯定意味着您犯了错误。也就是说,大多数编译器都有一些设置会将警告报告为错误,如果你将警告级别提高到足够高,编译器可能会说&#34;这是如此可疑,以至于我是假设你搞砸了什么。&#34;
关于你的最后一个 - 为什么
bool a = accept;
最终将a
设置为true?
在C ++中,任何非空指针都会隐式转换为true,任何空指针都会隐式转换为false。在C ++中,函数可以隐式转换为指向自身的指针,因此在这种情况下accept
计算为accept
函数的地址,该函数是非空的,因此它将a
设置为{ {1}}。当你写下
true
该值打印为1,因为cout << a << endl;
值默认打印为1和0而不是bool
和true
。那就是说,你可以写
false
并且您会看到cout << boolalpha << a << endl;
打印出来。
希望这有帮助!