W C++ 11, nowa uniwersalna składnia inicjalizacji może być również użyta do wywołania normalnego konstruktora (który nie przyjmuje parametru initializer_list). Chociaż patrząc na to nie jest źle, myślę, że może to spowodować problem w rzeczywistym użyciu.Uniwersalna inicjalizacja C++ 11 powoduje nieoczekiwaną inicjalizację?
Więc załóżmy w moim projekcie używam biblioteki, która pochodzi z następujących klas:
class Foo
{
public:
Foo(int size, int value); // create 'size' number of elements
Foo(initializer_list<int> list); // create elements as in 'list'
}
w projekcie jest używany w ten sposób:
Foo foo{10, 2}; // initialize foo with 2 elements: 10 and 2
Teraz biblioteka ma nowego release i w nowym wydaniu autor usunął 2 konstruktora, który pobiera initializer_list (albo przez cel lub przez pomyłkę). Nie zauważyłem zmiany, a mój projekt rozwija się szczęśliwie, tak jak poprzednio, tylko z nieoczekiwanym zainicjowaniem foo (teraz jest to 10 elementów zamiast 2).
Inną wersją tego problemu jest to, że Foo miał tylko pierwszy konstruktor i używasz uniwersalnej składni inicjalizacyjnej do init foo, a teraz autor zdecydował się na dodanie drugiego konstruktora, a to samo powoduje, że foo będzie inicjowane z różnymi elementy bez zauważenia.
Chciałam poznać opinię innych osób na ten temat. Czy to jest prawdziwy problem, czy też zbytnio się martwię? Czy istnieje jakieś rozwiązanie, aby temu zapobiec? Dzięki.
Jest to z pewnością dobry argument przeciwko uważaniu go za "uniwersalny" i próbowaniu go używać powszechnie. Użyj poprawnej nazwy "inicjowanie listy" i używaj jej tylko wtedy, gdy chcesz ją zainicjować z listy. Lub gdy składnia zmusza Cię do np. Inicjalizacja w klasie lub w celu uniknięcia kłopotliwej analizy. (Ale to tylko moja opinia, a nie odpowiedź, bo tak naprawdę nie ma odpowiedzi). –
Scott Meyers bardzo dobrze opisuje to w Effective Modern C++ w punkcie 7 i tak, to jest prawdziwy problem. –
Bardzo fajne pytanie. Czy ktoś może wyjaśnić, dlaczego nawias '()' może zostać pominięty? – Chiel