“支架初始化”。 (C++)
我现在正在学习 C++,C++ Primer plus。但我只是想查看 cplusplus 网站并跳过一些文件处理。
我非常了解来自 java、php、Visual Basic 的文件处理基础知识。但我遇到了一条非常奇怪的线。
ostream os(&fb);
fb 代表一个文件缓冲区。我只是不明白它的语法,但我可以弄清楚它与:
ostream os = &fb;
但我从未真正读过这种初始化变量的方式。
所以我想知道。我是否只是愚蠢并一直错过了一个真正有用的功能?这种初始化方式是旧的吗?有什么不同吗?
提前致谢。
I'm learning C++ at the moment, C++ Primer plus. But I just felt like checking out the cplusplus website and skip a little forward to file handling.
I pretty much know the basics of file handling coming from java, php, visual basic. But I came across a pretty weird line.
ostream os(&fb);
fb represents a filebuf. I just don't get the syntax of this, but I can figure out that it's the same as:
ostream os = &fb;
But I never really read about this way of initializing variables.
So I'm wondering. Am I just senseless and missing out a real useful feature the entire time? Is this way of initializing just old? Is it something different?
Thanks in advance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
两种形式都执行初始化。第一种语法(使用
()
)称为直接初始化语法。第二种语法(使用=
)称为复制初始化语法。在大多数现实生活中,它们的行为是相同的,但两者之间确实存在差异。在左侧 (LHS) 和右侧 (RHS) 的类型相同(忽略任何 const/易失性限定符)的情况下,两者确实完全相同。语言标准明确指出,在这种情况下,
=
形式相当于()
形式。但是当类型不同时(并且 LHS 类型是类类型),这两种形式通常会以不同的方式工作。
复制初始化形式的工作原理如下:将 RHS 值转换为 LHS 类型的临时对象(通过任何可能的方式:标准转换、转换运算符、转换构造函数)。然后使用 LHS 类的复制构造函数将临时对象复制到 LHS 对象。
直接初始化形式的工作原理如下:仅考虑 LHS 的所有构造函数,并通过使用重载决策选择最合适的一个。
直接初始化形式的工作原理如下
您可以立即注意到复制初始化语法无条件地使用复制构造函数(复制和中间临时可以被优化掉,但从概念上讲它们就在那里)。如果 LHS 类没有可访问的复制构造函数,则复制初始化无条件地变得格式错误,而直接初始化可能仍然有效。
此外,应用于某些构造函数的关键字
explicit
将影响哪种形式的初始化可用于哪种类型的组合。Both forms perform initialization. The first syntax (with
()
) is called direct-initialization syntax. The second syntax (with=
) is called copy-initialization syntax. They will act same in most real-life cases, but there are indeed differences between the two.In situations when types on the left-hand side (LHS) and right-hand side (RHS) are identical (ignoring any const/volatile qualifiers), both are indeed exactly the same. The language standard explicitly states that in this case the
=
form is equivalent to()
form.But when the types are different (and the LHS type is a class type), these two forms will generally work differently.
The copy-initialization form works as follows: convert the RHS value to the temporary object of LHS type (by any means possible: standard conversion, conversion operator, conversion constructor). And then use the copy constructor of the LHS class to copy the temporary object to the LHS object.
The direct initialization form work as follows: just consider all constructors of LHS and choose the most appropriate one by using overload resolution.
You can immediately notice that the copy-initialization syntax unconditionally uses the copy constructor (the copying and the intermediate temporary can be optimized away, but conceptually they are there). If the LHS class has no accessible copy-constructor, the copy-initialization unconditionally becomes ill-formed, while direct-initialization might still work.
Also, the keyword
explicit
applied to certain constructor will affect which form of initialization is available for which combinations of types.一个小程序,用于查看何时调用复制构造函数以及何时调用重载赋值运算符函数:
输出:
因此,在您的情况下,在这两种情况下都会调用 ostream 的复制构造函数。
A small program to see when copy constructor is called and when overloaded assignment operator function is called:
Output:
So in your case, the copy constructor of ostream is called in both the occasions.
也许您应该阅读此和这个
Perhaps you should read this and this
函数调用初始化的一个重要好处是它们还可以与采用多个参数的构造函数一起使用。例如,fstream 构造函数可以采用两个参数:
直到 C++0x 统一初始化 广泛可用,函数调用初始化是处理多参数构造函数的唯一方法。
One important benefit of function-call initialization is that they also work with constructors that take multiple arguments. For example, an fstream constructor can take two parameters:
Until C++0x uniform initialization is widely available, function-call initialization is the only way to handle multiple argument constructors.
根据我的理解, &var 是 var 变量的别名,与您使用哪一个无关。
--------添加 -----------------
下面的代码取自 Stroustrup 的书。从中可以清楚地看出,两者都是同一变量的别名。也有如下说法。
“参数传递的语义被定义为初始化的语义,因此当调用时,增量的参数 aa 变成了 x 的另一个名称。”这就是为什么我将 &x 称为 x 的别名。
<代码>
无效增量(int&aa){aa++; }
void f()
{
整数x=1;
增量(x);
}
From my understanding, &var is a alias for the var variable and doesn't matter which one you use.
--------Addition -----------------
The below code is taken from Stroustrup book.From this its clear that both are alias to the same variable. It also says as below.
"The semantics of argument passing are defined to be those of initialization, so when called, increment's argument aa became another name of x." Thats why I refered to &x to be alias of x.
void increment(int& aa) { aa++; }
void f()
{
int x = 1;
increment(x);
}