我正在学习C ++,C ++ Primer plus。但我只是想看看cplusplus网站并跳过一点文件处理。
我非常了解来自java,php,visual basic的文件处理的基础知识。但我遇到了一个非常奇怪的路线。
ostream os(&fb);
fb代表一个filebuf。我只是没有得到这个的语法,但我可以弄清楚它与:
相同ostream os = &fb;
但我从未真正了解过这种初始化变量的方式。
所以我很想知道。我只是毫无意义,错过了一个真正有用的功能吗?这种初始化方式只是旧的吗?这有什么不同吗?
提前致谢。
答案 0 :(得分:6)
两个表单都执行初始化。第一种语法(带()
)称为直接初始化语法。第二种语法(带=
)称为复制初始化语法。它们在大多数现实生活中都会表现相同,但两者之间确实存在差异。
在左侧(LHS)和右侧(RHS)的类型相同(忽略任何const / volatile限定符)的情况下,两者确实完全相同。语言标准明确指出,在这种情况下,=
表单相当于()
表单。
但是当类型不同(并且LHS类型是类类型)时,这两种形式通常会以不同的方式工作。
复制初始化表单的工作方式如下:将RHS值转换为LHS类型的临时对象(通过任何可能的方式:标准转换,转换运算符,转换构造函数)。然后使用LHS类的复制构造函数将临时对象复制到LHS对象。
直接初始化表单的工作原理如下:只考虑LHS的所有构造函数,并使用重载解析选择最合适的构造函数。
您可以立即注意到复制初始化语法无条件地使用复制构造函数(复制和中间临时可以被优化掉,但从概念上讲它们就在那里)。如果LHS类没有可访问的复制构造函数,则复制初始化无条件地变为格式错误,而直接初始化可能仍然有效。
此外,应用于某个构造函数的关键字explicit
将影响哪种形式的初始化可用于哪种类型的组合。
答案 1 :(得分:5)
答案 2 :(得分:5)
一个小程序,用于查看何时调用复制构造函数以及何时调用重载的赋值运算符函数:
#include <iostream>
using namespace std;
class test
{
public:
// default constructor.
test()
{
cout<<"Default Ctor called"<<endl;
}
// copy constructor.
test(const test& other)
{
cout<<"Copy Ctor called"<<endl;
}
// overloaded assignment operator function.
test& operator=(const test& other)
{
cout<<"Overload operator function called"<<endl;
return *this;
}
};
int main(void)
{
test obj1; // default constructor called.
test obj2 = obj1; // copy constructor called.
test obj3(obj2); // again copy constructor called.
obj1 = obj2; // overloaded assignment operator function.
return 0;
}
输出:
Default Ctor called
Copy Ctor called
Copy Ctor called
Overload operator function called
因此,在您的情况下,ostream的复制构造函数在两种情况下都会被调用。
答案 3 :(得分:1)
函数调用初始化的一个重要好处是它们也适用于带有多个参数的构造函数。例如,fstream构造函数可以使用两个参数:
std::fstream file("filename", ios_base::out);
直到C++0x uniform initialization广泛可用,函数调用初始化是处理多个参数构造函数的唯一方法。
答案 4 :(得分:0)
根据我的理解,&amp; var是var变量的别名,与你使用的变量无关。
--------加法-----------------
以下代码取自Stroustrup book。从中可以看出,两者都是同一个变量的别名。它还说如下。
“参数传递的语义定义为初始化的语义,因此在调用时,increment的参数aa成为x的另一个名称。”这就是为什么我把&amp; x称为x的别名。
void increment(int& aa) { aa++; }
void f()
{
int x = 1;
increment(x);
}