«Скобка инициализации». (C ++) - PullRequest
5 голосов
/ 26 декабря 2009

Я сейчас изучаю C ++, C ++ Primer plus. Но мне просто захотелось зайти на сайт cplusplus и немного перейти к обработке файлов.

Я в значительной степени знаю основы обработки файлов из Java, PHP, Visual Basic. Но я наткнулся на довольно странную линию.

ostream os(&fb);

fb представляет файлбуф. Я просто не понимаю синтаксис этого, но я могу понять, что он такой же, как:

ostream os = &fb;

Но я никогда не читал об этом способе инициализации переменных.

Так что мне интересно. Я просто бессмысленный и все время упускаю реальную полезную функцию? Этот способ инициализации просто старый? Это что-то другое?

Заранее спасибо.

Ответы [ 5 ]

6 голосов
/ 26 декабря 2009

Обе формы выполняют инициализацию . Первый синтаксис (с ()) называется синтаксисом прямой инициализации. Второй синтаксис (с =) называется синтаксисом инициализации копирования. Они будут действовать одинаково в большинстве реальных случаев, но между ними действительно есть различия.

В ситуациях, когда типы с левой стороны (LHS) и с правой стороны (RHS) идентичны (без учета любых константных / изменчивых квалификаторов), оба действительно одинаковы. Стандарт языка прямо заявляет, что в этом случае форма = эквивалентна форме ().

Но когда типы различаются (а тип LHS является типом класса), эти две формы обычно работают по-разному.

  • Форма инициализации копирования работает следующим образом: преобразовать значение RHS во временный объект типа LHS (любым возможным способом: стандартное преобразование, оператор преобразования, конструктор преобразования). А затем используйте конструктор копирования класса LHS для копирования временного объекта в объект LHS.

  • Форма прямой инициализации работает следующим образом: просто рассмотрите все конструкторы LHS и выберите наиболее подходящий, используя разрешение перегрузки.

Вы можете сразу заметить, что синтаксис инициализации копирования безоговорочно использует конструктор копирования (копирование и промежуточное временное копирование могут быть оптимизированы, но концептуально они есть). Если класс LHS не имеет доступного конструктора копирования, инициализация копирования безусловно становится некорректной, в то время как прямая инициализация все еще может работать.

Кроме того, ключевое слово explicit, применяемое к определенному конструктору, будет влиять на то, какая форма инициализации доступна для каких комбинаций типов.

5 голосов
/ 26 декабря 2009

Небольшая программа для просмотра, когда вызывается конструктор копирования и когда вызывается перегруженная функция оператора присваивания:

#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 вызывается в обоих случаях.

5 голосов
/ 26 декабря 2009

Возможно, вам следует прочитать это и это

1 голос
/ 27 декабря 2009

Одним из важных преимуществ инициализации вызова функции является то, что они также работают с конструкторами, которые принимают несколько аргументов. Например, конструктор fstream может принимать два параметра:

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

До тех пор, пока C ++ 0x равномерная инициализация не станет широко доступной, инициализация вызова функции является единственным способом обработки конструкторов с несколькими аргументами.

0 голосов
/ 27 декабря 2009

Насколько я понимаю, & var является псевдонимом для переменной var, и не имеет значения, какой из них вы используете.

-------- Дополнение -----------------

Приведенный ниже код взят из книги Страуструпа. Из этого ясно, что оба являются псевдонимами одной и той же переменной. Это также говорит как ниже.

«Семантика передачи аргументов определяется как инициализация, поэтому при вызове аргумент приращения aa становится другим именем x». Вот почему я назвал & x псевдонимом x.

void increment(int& aa) { aa++; }</p> <p>void f() { int x = 1; increment(x); }

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...