Рассмотрим эту программу:
#include <stdio.h>
struct S {
S() { print(); }
void print() { printf("%p\n", (void *) this); }
};
S f() { return {}; }
int main() { f().print(); }
Насколько я могу судить, существует только один объект S, построенный здесь. Отсутствует копия: нет копии, которую нужно исключить в первую очередь, и действительно, если я явно удалю конструктор копирования и/или перемещения, компиляторы продолжают принимать программу.
Однако я вижу два разных значения указателя. Это происходит из-за того, что моя платформа ABI возвращает тривиально-скопируемые типы, такие как эта, в регистры процессора, поэтому нет возможности с этим ABI избежать копирования. clang сохраняет это поведение даже при полной оптимизации вызова функции. Если я даю S нетривиальный конструктор копии, даже если он недоступен, тогда я вижу одно и то же значение, напечатанное дважды.
Первоначальный вызов print() происходит во время построения, который находится до начала жизненного цикла объекта, но использование this внутри конструктора обычно действует до тех пор, пока оно не используется таким образом, что требуется конструкция чтобы закончить - например, литье в производный класс, и, насколько я знаю, печать или сохранение его значения не требует завершения строительства.
Позволяет ли эта стандартная программа печатать два разных значения указателя?
Примечание. Я знаю, что стандарт позволяет этой программе печатать два разных представления одного и того же значения указателя, и технически я этого не исключал. Я мог бы создать другую программу, которая позволяет избежать сравнения представлений указателей, но было бы труднее понять, поэтому я хотел бы избежать этого, если это возможно.