initializer_list и разрешение перегрузки конструктора по умолчанию - PullRequest
4 голосов
/ 26 января 2012
#include <initializer_list>
#include <iostream>
using namespace std;

struct Y {};

struct X
{
    X(initializer_list<Y>) { cout << "yay" << endl; }
    explicit X() { cout << "boo" << endl; }
};

X f()
{
    return {};
}

int main()
{
    f();

    return 0;
}

Это печатает "бу".Почему не выводится «yay»?

В любом случае можно различить следующие две конструкции:

  1. X()
  2. X{}

или

  1. return X();
  2. return {};

или

void g(const X&)
  1. g(X())
  2. g({})

Спасибо.

Ответы [ 4 ]

5 голосов
/ 26 января 2012

Есть ли в любом случае дифференцировать следующие две конструкции:

Нет.Они не являются разными конструкциями.

Основная цель синтаксиса конструктора {} состояла в том, чтобы ввести равномерную инициализацию, чтобы инициализация работала везде одинаково.Если между ними есть разница, она не будет одинаковой.

Если вы хотите использовать пустой конструктор списка инициализатора, вы должны указать, что вы передаете список инициализатора явно.Вот так: return initializer_list<Y>{}; Конечно, одна из других целей унифицированной инициализации состоит в том, чтобы не нужно было так много печатать typenames, чтобы вы могли добиться того же эффекта с помощью return {{}};

5 голосов
/ 26 января 2012

return {}; всегда будет использовать конструктор по умолчанию, если он есть.

return X({}); или return {{}}; будут создавать из пустого списка инициализатора.

1 голос
/ 27 января 2012

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

Есть ли в любом случае различать следующие две конструкции: ...

X() - это всегда инициализация значения, а X{} - только инициализация значения, если X имеет конструктор по умолчанию. Если это агрегат, то X{} - это агрегатная инициализация (рекурсивная инициализация членов X с помощью {}). Если в нем есть только конструкторы списка инициализаторов и нет конструкторов по умолчанию, то X() недопустим и X{} может быть допустимым

struct A { A(initializer_list<int>); };
A a = A{}; // valid
A b = A(); // invalid

По существу, то, что делает X{}, зависит от того, что является X. Но X() всегда значение инициализируется.

... или вернуть X (); против возврата {};

Нечто упомянутое ... В return {} цель инициализируется при копировании списка, а в return X(); сначала выполняется прямая инициализация X. Но даже при том, что он инициализирован списком копирования, он может использовать конструктор по умолчанию explicit, потому что инициализация значения не заботится о explicit. Однако, когда вы делаете return {} и пытаетесь использовать явный конструктор не по умолчанию, вы выдаете ошибку

struct A {
  explicit A(initializer_list<int>);
};

A f() { return {}; } // error!

struct B { 
  explicit B();
};

B g() { return {}; } // OK
0 голосов
/ 26 января 2012

Вы можете быть немного более явным:

return initializer_list<Y>();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...