5

我现在正在学习 C++,C++ Primer plus。但我只是想看看 cplusplus 网站,然后稍微向前跳到文件处理。

我非常了解来自 java、php、visual basic 的文件处理基础知识。但是我遇到了一条非常奇怪的线。

ostream os(&fb);

fb 代表一个文件缓冲区。我只是不明白这个的语法,但我可以弄清楚它与以下内容相同:

ostream os = &fb;

但我从来没有真正读过这种初始化变量的方式。

所以我想知道。我是否只是毫无意义并且一直错过了一个真正有用的功能?这种初始化方式是旧的吗?有什么不同吗?

提前致谢。

4

5 回答 5

6

两种形式都执行初始化。第一种语法(with ())称为直接初始化语法。第二种语法(with =)称为复制初始化语法。在大多数现实生活中,它们的行为都是一样的,但两者之间确实存在差异。

在左侧 (LHS) 和右侧 (RHS) 的类型相同(忽略任何 const/volatile 限定符)的情况下,两者确实完全相同。语言标准明确指出,在这种情况下,=形式等同于()形式。

但是当类型不同时(并且 LHS 类型是类类型),这两种形式通常会有所不同。

  • 复制初始化形式的工作方式如下:将 RHS 值转换为 LHS 类型的临时对象(通过任何可能的方式:标准转换、转换运算符、转换构造函数)。然后使用LHS类的复制构造函数将临时对象复制到LHS对象中。

  • 直接初始化形式的工作方式如下:只需考虑 LHS 的所有构造函数,并使用重载决议选择最合适的构造函数。

您可以立即注意到复制初始化语法无条件地使用复制构造函数(复制和中间临时可以被优化掉,但从概念上讲它们就在那里)。如果 LHS 类没有可访问的复制构造函数,则复制初始化会无条件地变为格式错误,而直接初始化可能仍然有效。

explicit此外,应用于某些构造函数的关键字将影响哪种形式的初始化可用于哪种类型的组合。

于 2009-12-26T19:23:45.227 回答
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 的复制构造函数。

于 2009-12-26T15:15:27.270 回答
4

也许你应该阅读这个这个

于 2009-12-26T15:05:57.417 回答
1

函数调用初始化的一个重要好处是它们还可以与带有多个参数的构造函数一起使用。例如,一个 fstream 构造函数可以采用两个参数:

std::fstream file("filename", ios_base::out);

C++0x 统一初始化广泛可用之前,函数调用初始化是处理多参数构造函数的唯一方法。

于 2009-12-27T04:22:41.360 回答
0

据我了解, &var 是 var 变量的别名,与您使用哪个无关紧要。

- - - - 添加 - - - - - - - - -

下面的代码取自 Stroustrup 书。从这里可以清楚地看出两者都是同一个变量的别名。它还说如下。

“参数传递的语义被定义为初始化的语义,所以当被调用时,increment 的参数 aa 变成了 x 的另一个名称。” 这就是为什么我将 &x 称为 x 的别名。

void increment(int& aa) { aa++; }

void f() { int x = 1; increment(x); }

于 2009-12-27T04:06:12.753 回答