почему список инициализации C ++ стоит перед скобками? - PullRequest
0 голосов
/ 02 мая 2011

Я хочу знать, в чем разница в следующих двух классах.

пример 1:

class A
{
string name;
public:
  A(const char* _name):name(_name){}
  void print(){cout<<"A's name:"<<name<<endl;}
};

пример 2:

class A
{
string name;
public:
  A(const char* _name){name(_name);}
  void print(){cout<<"A's name:"<<name<<endl;}}

почему пример 1прошло, а последний не так?Спасибо

Ответы [ 6 ]

3 голосов
/ 02 мая 2011

В примере 1 вы сразу инициализируете строку с заданным значением.В примере 2 вы сначала создаете пустую строку, а затем назначаете ее.

Несмотря на некоторые различия в производительности и игнорирование возможных различий из-за обработки конструктора копирования и т. Д., По сути, это тот же результат.

Однако один развы используете член const, вам придется использовать способ примера 1, например, я обычно создаю уникальные идентификаторы следующим образом:

class SomeObject
{
    static unsigned int nextID = 0;
    const unsigned int ID;
    SomeObject() : ID(nextID++)
    {
        // you can't change ID here anymore due to it being const
    }
}
3 голосов
/ 02 мая 2011

Первый пример - фактическая инициализация. Он имеет ряд преимуществ, в том числе единственный способ настроить const членов и наличие надлежащей исключительной безопасности.

Второй пример недопустим C ++, AFAIK. Если бы вы вместо этого написали name = name_, то это было бы просто обычное задание. Конечно, это не всегда возможно; объект может быть const или не иметь определенного оператора присваивания. Этот подход также может быть менее эффективным, чем в первом примере, потому что объект инициализирован по умолчанию и .

Что касается , почему список инициализаторов находится перед телом конструктора; что ж, именно так был определен язык.

2 голосов
/ 02 мая 2011

Вот так определяется язык. Инициализаторы членов должны быть помещены перед телом конструктора.

1 голос
/ 02 мая 2011

В первом примере имя элемента инициализируется с помощью ctr, получающего char * в качестве параметра.

Во втором случае он инициализируется сначала ctr по умолчанию и позже получает значение оператором присваивания (operator =). Вот почему в вашем случае неправильно, что он уже построен, поэтому вы не можете снова использовать ctr, вы можете просто использовать оператор присваивания.

0 голосов
/ 02 мая 2011

Мотивация за списком инициализации обусловлена ​​тем, что поле const содержит объект по значению (в отличие от поля ссылки / указателя).

Такие поля должны быть инициализированы ровно один раз (из-за их постоянства),Если бы в C ++ не было списка инициализации, то ctor мог бы выглядеть примерно так:

class A {
public:
  const string s;
  const string t;

  A() {
    // Access to either s or t is not allowed - they weren't initialized
    s = "some-string";
    // now you can access s but you can't access t
    f(*this);

    t = "some other string";
    // From now you can access both ...
  }
}


void f(A& a) {
  // Can you access a.s or a.t?
  cout << a.s << a.t;
}

Без списка инициализации ctor может передать частично инициализированный объект типа A в функцию, и эта функцияне будет возможности узнать, какие поля еще инициализированы.Слишком рискованно и очень сложно проверить компилятору / компоновщику.

0 голосов
/ 02 мая 2011

Причина в том, что поиск имени работает по-разному в списках инициализаторов и телах функций:

class A
{
  std::string foo; // member name
public:
  A(const char* foo) // argument name
    : foo(foo) // member foo, followed by argument foo.
  {
    std::cout << foo; // argument foo.
  }
};

Если бы список инициализаторов находился внутри тела функции, между членом foo и аргументом * была бы неоднозначность1005 *.

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