Подтвердить что ты не робот

С++ всегда использует явный конструктор

Прочитав следующий блог:

http://xania.org/200711/ambiguous-overloading

Я начал спрашивать себя: "Должен ли я не всегда явно определять мои конструкторы?"

Итак, я начал читать больше, чем выяснил эту статью:

http://www.sjbrown.co.uk/2004/05/01/always-use-explicit/

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

Я был бы рад услышать от некоторых из вас, что ваша мысль о манере, каков ваш опыт с предметом и несколько примеров для любого из них было бы хорошо.

4b9b3361

Ответ 1

Традиционная мудрость заключается в том, что конструкторы, принимающие один параметр (явно или эффективно с использованием параметров по умолчанию), должны быть отмечены explicit, если только они не определяют преобразование (std::string, будучи конвертируемым из const char*, одним из примеров последний). Вы сами выяснили причины, в которых неявные преобразования действительно могут сделать жизнь сложнее, чем она должна быть.

Возможно, очевидным исключением является конструктор копирования. Или, возможно, другим способом является рассмотрение того, что большинство типов конвертируются из и для себя, и что как таковой конструктор копирования не выделяется explicit большую часть времени.

Хотя может показаться, что маркировка всех других конструкторов explicit не повредит, я бы возразил против этого. Поскольку while explicit не влияет на конструктор, принимающий несколько аргументов в С++ 03, это имеет эффект в С++ 11. Поместить его в код:

struct foo {
    explicit foo(int i);
    foo(int i, int j);
    explicit foo(int i, int j, int k);
};

foo make_foo()
{
    /* Not C++11-specific: */
    // Error: no conversion from int to foo
    return 42;

    // Okay: construction, not conversion
    return foo(42);

    // Okay: constructions
    return foo(42, 42);
    return foo(42, 42, 42);

    /* C++11 specific: */
    // Error: no conversion from int to foo
    return { 42 };

    // Not an error, not a conversion
    return { 42, 42 };

    // Error! Constructor is explicit
    return { 42, 42, 42 };
    // Not an error, direct-initialization syntax
    return foo { 42, 42, 42 };
}

Я лично считаю ненужным подробное описание того, что в функции, возвращающей foo, я должен явно возвращать foo { 42, 42, 42 }. Я не понимаю, от чего меня защищает explicit. Я действительно хочу, чтобы синтаксис { initializers... } имел в виду "построить объект из заданных инициализаторов", а explicit попадает в путь, сохраняя при этом меня из ничего. (Так как { i } действительно сводится к i в контексте инициализации копирования - большую часть времени - я с удовольствием отдам это.)

Итак, я бы сказал, привыкнуть использовать explicit для унарных конструкторов и только тех.