问题描述
|
我发现可以使用与下面的示例所示名称相同的构造函数参数来初始化成员变量。
#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;
}
带参数-Wall -Wextra -pedantic
的g ++ 4.4不会给出警告,并且可以正常工作。它也适用于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初始化程序的expression-list中的名称在为其指定了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,
用的值初始化X :: b
构造函数参数i,初始化
X :: i与构造函数的值
参数i,并使用初始化X :: j
X :: i的值;这发生
每次X类的对象是
创建。 ]
[注意:因为
mem-initializer在
构造函数的范围,这个
指针可以在
mem初始化程序的表达式列表
指对象
初始化。 ]
如您所见,在上面的示例中还有其他有趣的事情,以及来自标准本身的注释。
顺便说一句,顺便说一句,为什么不接受该参数作为const引用:
Blah(const std::vector<int> & vec): vec(vec) {}
^^^^const ^reference
它避免了不必要的原始矢量对象的复制。
, 它可以保证始终有效(我经常使用)。编译器知道初始化列表的形式为:“ 5”,因此知道“ 7”中的第一个“ 6”必须是成员。现在,在用于初始化成员的参数上,可以使用两个成员,构造函数的参数和其他符号,就像构造函数中将出现的任何表达式一样。此时,它将应用常规查找规则,并且参数vec
隐藏成员vec
。
该标准的第12.6.2节涉及初始化,并解释了第2段处理成员查找和第7段处理参数查询的过程。
mem初始化程序的expression-list中的名称在为其指定了mem-initializer的构造函数的范围内进行评估。 [例:
class X {
int a;
int b;
int i;
int j;
public:
const int& r;
X(int i): r(a),j(this->i) {}
};
, 一个额外的反论点,或者也许只是要注意的一种情况是,使用move构造来初始化成员变量。
如果需要在构造函数的主体内使用成员变量,则需要通过this指针明确引用该成员变量,否则将使用处于未定义状态的移动变量。
template<typename B>
class A {
public:
A(B&& b): b(std::forward(b)) {
this->b.test(); // Correct
b.test(); // Undefined behavior
}
private:
B b;
};
, 正如其他人已经回答的那样:是的,这是合法的。是的,这是标准保证的。
而且我每次看到它都感到可怕,迫使我停下来:\“vec(vec)
?WTF?是的,vec
是成员变量... \”
这就是为什么很多人(包括我自己)喜欢使用命名约定的原因之一,该约定清楚地表明成员变量是成员变量。我看到的约定包括添加下划线后缀(vec_
)或an15ѭ前缀(m_vec
)。然后,初始化器将显示:vec_(vec)
/m_vec(vec)
,这很容易理解。