Отключить инициализацию члена класса по умолчанию перед кодом конструктора - PullRequest
0 голосов
/ 28 декабря 2018

В C ++ любой член класса, который является не , созданным в списке инициализации члена, создается по умолчанию перед выполнением конструктора содержащего класса.Тем не менее, это выглядит очень расточительно, если эта переменная-член просто собирается в любом случае внутри конструктора класса, в котором она находится в .

Я привел пример ниже, чтобы уточнить, что я имею в виду.Здесь класс Example имеет переменную-член x типа LargeIntimidatingClass.Использование списка инициализации члена (первый конструктор в Example) x создается только один раз.Однако, если x не может быть разумно сконструирован с использованием списка инициализации члена, он создается дважды!

//This class used as part of the example class further below
class LargeIntimidatingClass {
    // ...
    //many member variables and functions
    // ...

    LargeIntimidatingClass() {
        //Painfully expensive default initializer
    }

    LargeIntimidatingClass(int a, double b) {
        //Complicated calculations involving a and b
    }
};

//Here, this class has a LargeIntimidatingClass as a member variable.
class Example {
    LargeIntimidatingClass x;
    char c;

    //Basic member initialization list constructor. Efficient!
    Example(int a, double b, char c) : x(a,b), c(c) {}

    //What if the parameters to the LargeIntimidatingClass's constructor
    //need to be computed inside the Example's constructor beforehand?
    Example(std::string sophisticatedArgument) {
        //Oh no! x has already been default initialized (unnecessarily!)

        int a = something1(sophisticatedArgument);
        double b = something2(sophisticatedArgument);
        //x gets constructed again! Previous (default) x is totally wasted!
        x = LargeIntimidatingClass(a,b);

        c = something3(sophisticatedArgument);
    }
};

Да, я понимаю, что в этом глупом примере вы могли бы написать Example(string s) : x(f1(s),f2(s)), c(f3(s)) {}, но яконечно, вы можете себе представить ситуацию, когда вставлять кучу логики в список инициализации члена громоздко (или даже невозможно).

Возможно ли отключить конструктор по умолчанию для переменной-члена, если он не указан в инициализации членасписок

Ответы [ 3 ]

0 голосов
/ 28 декабря 2018

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

  1. Иметь (умный) элемент указателя на расширенный класс.
  2. Пусть член будет std:aligned_storage и создайте объект, разместив новый.Затем тщательно управляйте временем жизни объекта.
  3. Держите std:optional.Управляйте инициализацией и позволяйте типу библиотеки управлять остальными для небольшого увеличения размера объекта.
0 голосов
/ 28 декабря 2018

Вы не можете отключить конструкцию.Все члены класса должны быть инициализированы до достижения тела конструктора.Тем не менее, вы можете легко обойти проблему.Вы можете добавить приватную статическую функцию-член, которая получает a и b и возвращает LargeIntimidatingClass из нее, например

class Example {
    LargeIntimidatingClass x;
    char c;
    static LargeIntimidatingClass make_LargeIntimidatingClass(std::string sophisticatedArgument)
    {
        int a = something1(sophisticatedArgument);
        double b = something2(sophisticatedArgument);
        return LargeIntimidatingClass(a,b);
    }
    static char make_c(std::string sophisticatedArgument)
    {
        return something3(sophisticatedArgument);
    }
public:

    //Basic member initialization list constructor. Efficient!
    Example(int a, double b, char c) : x(a,b), c(c) {}

    // now we use helpers to initialize in the member initialization list
    Example(std::string sophisticatedArgument) : x(make_LargeIntimidatingClass(sophisticatedArgument), c(make_c(sophisticatedArgument) {
        //now everything is initialized correctly
    }
};
0 голосов
/ 28 декабря 2018

Можно ли отключить конструктор по умолчанию для переменной-члена, если она не указана в списке инициализации члена?

Нет, это невозможно.

...