Этот вопрос требует чистого способа реализации статического заводского метода в C++, и этот ответ описывает четкий способ сделать это. Оптимизация возвращаемого значения спасла бы нас от создания ненужной копии Object, тем самым создав такой способ создания Object так же эффективно, как непосредственный вызов конструктора. Накладные расходы на копирование i в id внутри частного конструктора незначительны, потому что это небольшой int.
 Однако вопрос и ответ не охватывают более сложный случай, когда Object содержит переменную экземпляра, которая является экземпляром класса Foo (который требует сложной логики инициализации), а не малым примитивным типом. Предположим, что я хочу построить Foo используя аргументы, переданные Object. Решение с использованием конструктора будет выглядеть примерно так:
class Object {
    Foo foo;
public:
    Object(const FooArg& fooArg) {
        // Create foo using fooArg here
        foo = ...
    }
}
Альтернативой со статическим заводским методом, аналогичным цитируемому ответу, было бы, как мне кажется:
class Object {
    Foo foo;
    explicit Object(const Foo& foo_):
        foo(foo_)
    {
    }
public:
    static Object FromFooArg(const FooArg& fooArg) {
        // Create foo using fooArg here
        Foo foo = ...
        return Object(foo);
    }
}
 Здесь накладные расходы на копирование foo_ на foo больше не обязательно незначительны, так как Foo может быть произвольно сложным классом. Более того, насколько я понимаю (C++ новичок здесь, поэтому я могу ошибаться), этот код неявно требует, чтобы конструктор копирования был определен для Foo.
Что было бы таким же чистым, но и эффективным способом реализации этой модели в этом случае?
Чтобы предвидеть возможные вопросы о том, почему это уместно, я считаю, что конструкторы с логикой сложнее, чем просто копирование аргументов как анти-шаблон. Я ожидаю, что конструктор:
- гарантированно работать, а не бросать исключения,
- и не делайте тяжелых расчетов под капотом.
Таким образом, я предпочитаю ставить сложную логику инициализации в статические методы. Более того, такой подход обеспечивает дополнительные преимущества, такие как перегрузка по имени статического заводского метода, даже если типы входных аргументов одинаковы, и возможность четко указывать, что делается внутри имени метода.
