Рассмотрим следующую программу:
#include <iostream>
#include <utility>
class T {
public:
T() { printf("address at construction: %zx\n", (uintptr_t)this); }
// T(const T&) { printf("copy-constructed\n"); } // helps
// T(T&&) { printf("move-constructed\n"); } // helps
// T(const T&) = default; // does not help
// T(T&&) = default; // does not help
};
T f() { return T(); }
int main() {
T x = f();
printf("address after construction: %zx\n", (uintptr_t)&x);
return 0;
}
Компиляция с g++ -std=c++17 test.cpp
дает следующий результат (то же самое с clang++
):
address at construction: 7ffcc7626857
address after construction: 7ffcc7626887
Основываясь на справочнике по C++, я ожидаю, что программа выведет два одинаковых адреса, потому что копирование/перемещение должно гарантированно исключаться (по крайней мере, в С++ 17).
Если я явно определяю либо конструктор копии, либо конструктор перемещения, либо и то, и другое (см. закомментированные строки в примере), программа выдает ожидаемый результат (даже с C++11):
address at construction: 7ffff4be4547
address after construction: 7ffff4be4547
Простая установка конструкторов копирования/перемещения на default
не помогает.
В ссылке прямо указано
[Конструкторы копирования/перемещения] не обязательно должны присутствовать или быть доступными
Итак, что мне здесь не хватает?