C++ 在初始化列表中初始化与在构造函数中初始化之间的区别
我不确定我的问题的标题是否正确,请随意更正。我认为:C++ 在初始化列表中初始化与在构造函数中初始化之间的区别,c++,C++,我不确定我的问题的标题是否正确,请随意更正。我认为: 在初始化列表中初始化相当于 inta=a 在构造函数中初始化相当于 inta;a=a 但我仍然无法找出以下输出的原因: #include <iostream> using namespace std; class test { int a,b; public: /* test(int a, int b): a(a), b(b) {} //OUTPUT: 3 2 test(
inta=a代码>
inta;a=a代码>
#include <iostream>
using namespace std;
class test
{
int a,b;
public:
/*
test(int a, int b): a(a), b(b) {} //OUTPUT: 3 2
test(int a, int b) { a = a; b = b;} //OUTPUT: -2 1972965730
test(int c, int d) { a = c; b = d;} //OUTPUT: 3 2
Hence it does work without this pointer. Unless the variable names are same
*/
void print() { cout<<a<<" "<<b<<"\n";}
};
int main()
{
test A(3,2);
A.print();
return 0;
}
这是不对的。它对数据成员没有任何作用。应该是
test(int a, int b) { this->a = a; this->b = b;}
这是不对的。它对数据成员没有任何作用。应该是
test(int a, int b) { this->a = a; this->b = b;}
试着替换
test(inta,intb){a=a;b=b;}
withtest(inta,intb){this->a=a;this->b=b;}
我的编译器(msvc)生成所需的结果。尝试替换
test(inta,intb){a=a;b=b;}
withtest(inta,intb){this->a=a;this->b=b;}
我的编译器(msvc)生成所需的结果。每个函数都引入了一个新的作用域。当您将构造函数定义为
test(int a, int b) { a = a; b = b; }
test(int c, int d) { a = c; b = d; }
隐藏类成员。编译器无法知道左边的a
属于该类,右边的a
是一个参数
当您将构造函数声明为
test(int a, int b) { a = a; b = b; }
test(int c, int d) { a = c; b = d; }
您没有这个问题,因为不再有命名冲突
在建议的修复中,同样的推理适用:
test(int a, int b) { this->a = a; this->b = b; }
通过使用this
指针明确限定lhsa
是类成员,该指针隐式传递给每个成员函数,包括构造函数。但是,此代码并不等同于使用初始化列表初始化。你的问题是正确的:
inta=a代码>
inta;a=a代码>
test(int a, int b): a(a), b(b) {}
每个函数都引入了一个新的作用域。当您将构造函数定义为
test(int a, int b) { a = a; b = b; }
test(int c, int d) { a = c; b = d; }
隐藏类成员。编译器无法知道左边的a
属于该类,右边的a
是一个参数
当您将构造函数声明为
test(int a, int b) { a = a; b = b; }
test(int c, int d) { a = c; b = d; }
您没有这个问题,因为不再有命名冲突
在建议的修复中,同样的推理适用:
test(int a, int b) { this->a = a; this->b = b; }
通过使用this
指针明确限定lhsa
是类成员,该指针隐式传递给每个成员函数,包括构造函数。但是,此代码并不等同于使用初始化列表初始化。你的问题是正确的:
inta=a代码>
inta;a=a代码>
test(int a, int b): a(a), b(b) {}
在初始化列表中,语法是这样的:parens
()
之外的每个变量名都是类成员。parens中包含的是作用域中发生的任何内容—无论是类成员还是构造函数参数。参数将隐藏类成员
因此,您可以安全地执行以下操作:
class MyClass
{
int i;
MyClass(int i): i(i) {}
// ^-must be class member
};
编译器将正确地使用paren内部的参数来初始化paren外部的类成员
paren中发生的事情与构造函数体中发生的事情具有相同的作用域
因此:
名为i
的参数隐藏名为i
的类成员,因此在构造函数体中永远不会访问该类成员
您必须使用this
明确消除歧义:
class MyClass
{
int i;
MyClass(int i)
{
// now we set class member i to parameter i
this->i = i;
}
}
所有这些都在初始值设定项列表的语法中为您解决:
初始化列表基本上是为您执行:this->i=i
如果可能,您应该始终初始化初始化器列表中的成员。在初始化列表中,语法是这样的:parens
()
之外的每个变量名都是类成员。parens中包含的是作用域中发生的任何内容—无论是类成员还是构造函数参数。参数将隐藏类成员
因此,您可以安全地执行以下操作:
class MyClass
{
int i;
MyClass(int i): i(i) {}
// ^-must be class member
};
编译器将正确地使用paren内部的参数来初始化paren外部的类成员
paren中发生的事情与构造函数体中发生的事情具有相同的作用域
因此:
名为i
的参数隐藏名为i
的类成员,因此在构造函数体中永远不会访问该类成员
您必须使用this
明确消除歧义:
class MyClass
{
int i;
MyClass(int i)
{
// now we set class member i to parameter i
this->i = i;
}
}
所有这些都在初始值设定项列表的语法中为您解决:
初始化列表基本上是为您执行:this->i=i
如果可能,您应该始终初始化初始值设定项列表中的成员。有两个区别:在正文中给定值不是初始化,因为该值已初始化(基元类型除外)。在您的情况下,在第二个版本中,成员“a”被参数a遮蔽,但在初始化列表中它不是(因为您只能在初始化列表中初始化成员)。与
a(a)
i等效