Встроенная функция, возвращающая статически созданный объект - PullRequest
3 голосов
/ 21 июня 2011
inline Config& config()
{
    static Config *c = new Config();
    return *c;
}

Вышеприведенная функция возвращает указатель на класс Config, созданный один раз при вызове функции.

Сможет ли компилятор C ++ правильно встроить эту функцию?

Я имею в виду c - статический объект, и его создание в первый раз приведет к выделению new Config() где-то в коде. Но когда функция вызывается во второй раз, что будет на месте config()? Встроенный с? Или вызов функции?

Ответы [ 4 ]

3 голосов
/ 21 июня 2011

У вас, кажется, есть небольшое недопонимание о том, как работают такие статические переменные. Похоже, вы думаете, что компилятор выдает один набор кода при первом вызове функции, а другой - каждый раз. Это не тот случай. Вы могли бы рассмотреть следующее преобразование.

bool initialized = false;
Config* c;

inline Config& config() {
    if(!initialized) {
        c = new Config();
        initialized = true;
    }
    return *c;
}

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

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

2 голосов
/ 21 июня 2011

Это зависит от компилятора, но из того, что я видел в MSVC, для этого будут встроены два глобальных параметра (на уровне сборки). один является логическим значением, указывающим, был ли введен статический переменный, а другой - для действительного статического параметра.

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

1 голос
/ 22 июня 2011

Какой смысл динамического распределения, если можно спросить?Я бы избавился от этого:

inline Config& config()
{
    static Config c = Config();
    return c;
}

Если Config не POD, вы даже можете просто сказать static Config c; и получить ту же семантику.

1 голос
/ 21 июня 2011

Если инлайнер не может обрабатывать такие тривиальные случаи, как этот, никакие функции никогда не будут встроены вообще.

...