使用与C ++标准允许的成员variables相同的构造函数参数名称来初始化成员variables?

我发现可以用下面的例子中显示的同名的构造函数参数来初始化成员variables。

#include <cstdio> #include <vector> class Blah { std::vector<int> vec; public: Blah(std::vector<int> vec): vec(vec) {} void printVec() { for(unsigned int i=0; i<vec.size(); i++) printf("%i ", vec.at(i)); printf("\n"); } }; int main() { std::vector<int> myVector(3); myVector.at(0) = 1; myVector.at(1) = 2; myVector.at(2) = 3; Blah blah(myVector); blah.printVec(); return 0; } 

g ++ 4.4与参数-Wall -Wextra -pedantic给出警告并且正常工作。 它也适用于clang ++。 我想知道C ++标准对此有何评论? 它是合法的,并保证始终工作?

我想知道C ++标准对此有何评论? 它是合法的,并保证始终工作?

是。 这是完全合法的。 完全符合标准。

 Blah(std::vector<int> vec): vec(vec){} ^ ^ | | | this is the argument to the constructor this is your member data 

既然你问了标准中的参考,这里就是一个例子。

§12.6.2/ 7

mem-initializerexpression式列表中的名称将在mem-initializer指定的构造函数的作用域中进行计算。

 [Example: class X { int a; int b; int i; int j; public: const int& r; X(int i): r(a), b(i), i(i), j(this->i) {} //^^^^ note this (added by Nawaz) }; 

初始化X :: r来引用X :: a,用构造函数参数i的值初始化X :: b,用构造函数参数i的值初始化X :: i,并用该值初始化X :: j X :: i; 每当创build一个类X的对象,就会发生这种情况。 ]

[注意:因为mem-initializer是在构造函数的范围内求值的,所以这个指针可以用在mem-initializer的expression式列表中来引用被初始化的对象。 ]

正如你所看到的,在上面的例子中还有其他有趣的事情要注意,标准本身的评论也是如此。


顺便说一句,作为边注,为什么你不接受参数作为const引用:

  Blah(const std::vector<int> & vec): vec(vec) {} ^^^^const ^reference 

它避免了原始vector对象的不必要的副本。

这是保证总是工作(我经常使用它)。 编译器知道初始化器列表的forms是: member(value) ,所以它知道vec(vec)中的第一个vec必须是成员。 现在,在初始化成员的参数上,可以使用成员,构造函数的参数和其他符号,就像在构造函数中存在的任何expression式一样。 此时它应用常规查找规则,参数vec隐藏成员vec

该标准的第12.6.2节涉及初始化,它解释了第2段涉及查找成员和第7段的过程,并查找了参数。

mem-initializerexpression式列表中的名称将在mem-initializer指定的构造函数的作用域中进行计算。 [例:

 class X { int a; int b; int i; int j; public: const int& r; X(int i): r(a), b(i), i(i), j(this->i) {} };