C++ 使用与C+允许的成员变量相同的构造函数参数名称初始化成员变量+;标准
我发现可以使用与下面示例中相同名称的构造函数参数初始化成员变量C++ 使用与C+允许的成员变量相同的构造函数参数名称初始化成员变量+;标准,c++,C++,我发现可以使用与下面示例中相同名称的构造函数参数初始化成员变量 #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<ve
#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;
}
#包括
#包括
课堂废话{
std::vec;
公众:
Blah(std::vector vec):vec(vec)
{}
void printVec(){
对于(无符号整数i=0;i
我想知道C++标准是什么意思?它合法并保证总是工作吗?< /P>
是的。这是完全合法的。完全符合标准
Blah(std::vector<int> vec): vec(vec){}
^ ^
| |
| this is the argument to the constructor
this is your member data
初始化X::r以引用X::a,
使用的值初始化X::b
构造函数参数i,初始化
具有构造函数值的X::i
参数i,并使用
X::i的值;这将发生
每次打开类X的对象时
创建。]
[注:因为
mem初始值设定项在
构造函数的作用域,此
指针可用于
mem初始值设定项的表达式列表
指正在处理的对象
已初始化。]
正如您所看到的,在上面的示例中还有其他有趣的事情需要注意,以及来自标准本身的注释
顺便说一句,作为旁注,为什么不接受参数作为常量引用:
Blah(const std::vector<int> & vec): vec(vec) {}
^^^^const ^reference
Blah(const std::vector&vec):vec(vec){
^^^^常量引用
它避免了原始vector对象的不必要副本。它保证始终工作(我经常使用它)。编译器知道初始值设定项列表的形式为:member(value)
,因此它知道vec(vec)中的第一个vec
必须是成员。现在在初始化成员的参数上,可以使用两个成员、构造函数的参数和其他符号,就像在构造函数内部的任何表达式中一样。此时,它应用常规查找规则,参数vec
隐藏成员vec
本标准第12.6.2节涉及初始化,并解释了第2段涉及成员查找和第7段涉及参数查找的过程
mem初始值设定项的表达式列表中的名称在为其指定mem初始值设定项的构造函数的范围内求值。[示例:
正如其他人已经回答的那样:是的,这是合法的。是的,标准保证了这一点
每次看到它我都觉得很可怕,迫使我停下来:“vec(vec)
?WTF?啊,是的,vec
是一个成员变量…”
这就是包括我在内的许多人喜欢使用命名约定的原因之一,该约定明确了成员变量是成员变量。我见过的约定包括添加下划线后缀(vec_u
)或m_
前缀(m_vec
)。然后,初始值设定项显示:vec_vec(vec)
/m_-vec(vec)
,这是一个不需要动脑筋的问题。另外一个反参数,或者可能需要注意的是使用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;
};
模板
甲级{
公众:
A(B&&B):B(标准:转发(B)){
这->b.test();//正确
b、 test();//未定义的行为
}
私人:
B B;
};
Thx快速回答,但是在标准文档(n3290)中我找不到初始化列表,哪章?在C++0x中,最好按值接受它,然后将它移动到它的目标:Blah(std::vector vec):vec(std::move(vec)){}
。在C++03中可以这样模拟:Blah(std::vector vecSrc){std::swap(vec,vecSrc);}
@Tomalak:lol,我仍然很惊讶你发现这是不可读的。这很直截了当,而且,我认为,这是一个普通的地方。@GMan:我仍然把它归类为“把戏”.我知道它是做什么的,但从代码中一眼就看不出它意味着什么,我认为。你必须仔细考虑这些步骤,才能意识到原始对象没有被移动到任何地方。虽然这是合法的,但这是一种不好的做法。使用-Wshadow(或等效物)时会弄脏水,并使您面临更有害的编程错误。好问题。我实际上一直在使用这种“风格”很多。从来没有怀疑过这是允许的。+1对于这里的关键点,其他人都没有说:这是有效的,因为应用了与在ctor主体中使用的相同的查找规则,这是关键点,这意味着参数隐藏/隐藏成员,这就是为什么它有效(对于单词“work”的某些定义);任何隐藏/阴影都是拙劣的。在:x(y),y(y)中检测错误比在:m_x(in_y),m_y(in_y)中检测相同的错误更容易。修饰最少的名字会减少分心,让读者只关注基本内容,最终产生错误的几率也会降低。标准中的这些规则并不是偶然选择的,它们是有目的的。
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) {}
};
template<typename B>
class A {
public:
A(B&& b): b(std::forward(b)) {
this->b.test(); // Correct
b.test(); // Undefined behavior
}
private:
B b;
};