现代C++构造函数中对象名后加英文分号的语法疑问
C++构造函数中奇怪语法的疑问与解析
你20年前有C++编程经验,现在重新接触后遇到了语法困惑——用Apple clang 15.0.0编译器时,以为构造函数里能用rd{};初始化对象,结果写出了rd;{};这类能编译但看不懂的代码。先明确:你代码里的那些写法完全不是正确的成员初始化方式,只是编译器把它们拆成了无意义的独立语句,碰巧没报错而已。
先拆解你代码里的疑惑部分:
rd; {};:rd;是一个表达式语句,只是引用了成员变量rd,没有任何实际操作;后面的{};是空代码块,同样啥也不做。random_device对象rd其实是默认初始化的,和这行代码无关。gen; {rd();};:gen;同样是无意义的成员变量引用;{rd();};是一个代码块,里面调用rd()生成了随机数,但这个值完全没被用到。mt19937 gen也是默认初始化的,根本没用到你想要的种子,和你的设计目标不符。dist; {0.0, 1.0;};:dist;无意义;{0.0, 1.0;}是代码块,里面是逗号表达式(结果为1.0),但同样没被使用。只不过normal_distribution默认就是均值0、标准差1,所以碰巧效果对了,但写法完全错误。
正确的初始化方式
C11及以后,成员变量的初始化应该用构造函数初始化列表,这才是符合现代C语法的写法,也能实现你想要的逻辑:
#include <iostream> #include <random> using namespace std; class normRand { public: random_device rd; mt19937 gen; normal_distribution<double> dist; // 用初始化列表完成成员初始化 normRand() : rd(), gen(rd()), dist(0.0, 1.0) { // 构造函数体无需额外逻辑,为空即可 } double val() { return dist(gen); } }; normRand myNormRand; int main() { cout << myNormRand.val(); return 0; }
初始化列表的作用:
: rd():显式默认初始化random_device(可省略,因为成员会自动默认初始化,写出来更清晰)gen(rd()):用rd()生成的随机值作为种子,初始化mt19937生成器,这才是你原本想要的逻辑dist(0.0, 1.0):显式指定正态分布的均值和标准差,替代默认初始化(虽然默认值刚好符合需求,但显式写出更易读)
为什么你试的rd{};不行?
在构造函数体里写rd{};,会创建一个局部的random_device对象,名字也叫rd,会遮蔽类的成员变量rd,这完全不是你想要的成员初始化操作。成员变量的初始化必须放在构造函数的初始化列表中,而不是函数体里重新创建局部对象。
关于编译器提示“对象名是表达式”
当你写rd;时,这是一个合法的表达式语句,它的作用是求值成员变量rd本身——虽然这个操作没有实际意义,但语法上是允许的,所以编译器会提示你这是一个表达式。
内容的提问来源于stack exchange,提问作者ProfBobK
相关产品推荐
相关产品推荐

