В S s = S() гарантируется, что временное создание не будет создано?
В следующем коде pS
и s.pS
гарантированно будут равны в последней строке? Другими словами, в выражении S s = S();
можно ли быть уверенным, что временная S
не будет построена?
#include <iostream>
using namespace std;
struct S
{
S() { pS = this; }
S* pS;
};
int main()
{
S s = S();
S* pS = &s;
cout << pS << " " << s.pS << endl;
}
В каждом компиляторе я тестировал это в pS == s.pS
, но я недостаточно знаком со стандартом, чтобы убедиться, что это гарантировано.
Ответы
Ответ 1
НЕТ
Компилятор не обязан копировать elision. Стандарт просто указывает, что [class.copy]:
При выполнении определенных критериев реализации разрешено опускать конструкцию копирования/перемещения объекта класса [...]
Я могу отключить копирование с помощью -fno-elide-constructors
, а затем два указателя, безусловно, будут отличаться. Например:
$g++ -std=c++11 -Wall -pedantic -fno-elide-constructors -Wall -Wextra main.cpp && ./a.out
0x7fff5a598920 0x7fff5a598930
И в общем случае, если мы добавим S(S&& ) = delete
, то приведенный выше код даже не будет компилироваться.
Ответ 2
Большинство компиляторов выполняет так называемый copy/move elision, который указан стандартом С++. Но это не гарантировано. Например, вы можете скомпилировать с -fno-elide-constructors
в gcc, и вы увидите все конструкторы во всей их славе.
Пример Live на Coliru
Ответ 3
Нет никакой гарантии, что временного не будет. Но компиляторы Big Three оптимизируют его (даже с помощью переключателя -O0
).
Чтобы гарантировать отсутствие временных ограничений, просто напишите:
int main()
{
// ...
S s{};
// ...
}
Или просто S s;
.