我的程序崩溃了,没有可用的调试器,所以我用 printfs 来控制它,将其缩小到(冗长的)初始值设定项列表,并尝试通过在每个值之前填充
printf(...),
来显示哪个初始值设定项表达式导致崩溃表达式,所以它看起来像这样:
#include <cstdio>
class X
{
public:
int a_;
int b_;
X(int a, int b);
};
X::X(int a, int b) :
a_(printf("Initializing a\n"), a),
b_(printf("Initializing b\n"), b)
{}
int main() {
X x(1,2);
return 0;
}
我的推理是逗号运算符应该吞掉 printf 的返回值,执行以下表达式,并正常初始化属性。相反,我收到了一个错误:
hw.cpp: In constructor 'X::X(int, int)':
hw.cpp:12:5: error: expression list treated as compound expression in mem-initializer [-fpermissive]
12 | a_(printf("Initializing a\n"), a),
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
hw.cpp:13:5: error: expression list treated as compound expression in mem-initializer [-fpermissive]
13 | b_(printf("Initializing b\n"), b)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
我通过用额外的括号将逗号操作括起来成功地解决了这个问题
a_((printf("Initializing a\n"), a)),
但我仍然有点困惑 g++ 正在尝试但未能实现按要求执行逗号操作符。有人可以解释一下吗?
表达式
a_(printf("Initializing a\n"), a)
被视为带有两个参数的构造函数调用,而 int
不存在这两个参数。当您将括号括起来时,它会被解析为单个参数。因此,现在里面有一个逗号运算符。
成员初始值设定项列表的 C++ 语法包括一个逗号分隔的列表,适用于成员需要多个参数来初始化的情况:
struct small
{
small(int x, int y, int z) {}
};
struct large
{
small part1, part2;
large(): part1(1, 2, 3), part2(22, 33, 44) {}
};
在您的示例中,您有
int
,其构造函数只有一个参数。但您的代码看起来想要使用 2 个参数调用其构造函数。您想要的代码的另一种解释是使用包含逗号运算符的单个参数进行调用。如果您想选择它,则必须使用额外的括号。
这不是语法上的歧义——在该上下文中,逗号分隔的列表意味着使用一定数量的参数进行构造。但我猜编译器试图提供额外的帮助,因此它提到了对代码的这种(非法)解释。