При условии отсутствия оптимизации компилятора, сколько раз этот объект будет создан? - PullRequest
0 голосов
/ 27 февраля 2019

При условии отсутствия оптимизации компилятора.Сколько раз будет создан объект типа OutputBuffer_s?

#include <iostream>
#include <vector>

struct OutputBuffer_s {
    int encoded[10];
};

OutputBuffer_s func() {

    OutputBuffer_s s;

    return s;
}

int main() {
    OutputBuffer_s a = func();
}

Первоначально я предполагал три раза.

1) Когда вызывается func (), объект s будет созданв стеке.

2) Когда func () выходит из области видимости, он возвращает копию объекта s в main ().

3) Копирование значения в объект aв main (), так как значение, возвращаемое func (), будет временным.

Я знаю, что я здесь не прав, так как я скомпилировал с -O0 в g++, но я мог видеть только одно созданиепосле переопределения конструкторов.Я хочу знать, где и почему я не прав.

Ответы [ 2 ]

0 голосов
/ 27 февраля 2019

C ++ 17 представил Временную материализацию, которую я цитирую:

Значение любого полного типа T может быть преобразовано в значение x того же типа T. Это преобразование инициализирует временный объектвведите T из значения prvalue, оценив значение prvalue с временным объектом в качестве объекта результата, и создаст значение xvalue, обозначающее временный объект.Если T является классом или массивом типа класса, он должен иметь доступный и не удаляемый деструктор.

В этом случае дополнительные вызовы contructor станут операцией move .До C ++ 17, где разрешение на копирование не было обязательным, компилятор обычно копировал elide.Насколько я знаю, в вашем случае компилятор все равно скопирует elide (попробуйте Godbolt и проверьте созданную сборку).

Для полного ответа один вызов конструктора и один ход.

0 голосов
/ 27 февраля 2019

Что у вас здесь copy-elison .

Разрешает копировать и перемещать (начиная с C ++ 11) конструкторы, что приводит к семантике передачи по значению при нулевом копировании.

GCC может исключить конструкторы даже с опцией -O0.Это то, что здесь происходит.Если вы хотите специально предотвратить elision, вы можете использовать опцию -fno-elide-constructors.

Если вы используете эту опцию, будет один вызов конструктора и два вызова конструктора move для C ++ 11.

См. Демоверсию здесь.

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

См. демонстрацию здесь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...