Почему sizeof ссылочного типа дает вам размер этого типа?
Согласно стандарту, в [expr.sizeof] (5.3.3.2) получаем:
При применении к эталонному или ссылочному типу, результатом является размер ссылочного типа.
Это, похоже, согласуется с тем, что ссылки не указаны [dcl.ref] (8.3.2.4):
Не указано, нужна ли ссылка для хранения
Но мне кажется довольно странным иметь такую несогласованность внутри языка. Независимо от того, требует ли ссылка для хранения, не важно ли было бы определить, какой размер использует эта ссылка? Увидеть эти результаты просто не так:
sizeof(vector<int>) == 24
sizeof(vector<int>*) == 8
sizeof(vector<int>&) == 24
sizeof(reference_wrapper<vector<int>>) == 8
Какова причина отсутствия sizeof(T&) == sizeof(T)
по определению?
Ответы
Ответ 1
Выбор несколько произволен, и попытка полностью оправдать любой вариант приведет к циркулярным метафизическим аргументам.
Цель ссылки - быть (псевдоним для) самого объекта; под этим рассуждением имеет смысл иметь одинаковый размер (и адрес), и именно это указывает язык.
Абстракция негерметична - иногда ссылка имеет собственное хранилище, отдельно от объекта, что приводит к аномалиям, подобным тем, которые вы указываете. Но у нас есть указатели на то, когда нам нужно иметь дело с "ссылкой" как отдельной сущностью к объекту.
Ответ 2
Аргумент 1: Ссылка должна быть синонимом вашего объекта, поэтому интерфейс ссылки должен быть точно таким же, как интерфейс объекта, также все операторы должны работать одинаково на объекта и ссылки (кроме операторов типов).
Это будет иметь смысл в следующем коде:
MyClass a;
MyClass& b = a;
char a_buf[sizeof(a)];
char b_buf[sizeof(b)]; // you want b_buf be the same size as a_buf
memcpy(&a, a_buf, sizeof(a));
memcpy(&b, b_buf, sizeof(b)); // you want this line to work like the above line
Аргумент 2: С стандартной точки зрения С++ ссылки - это что-то под капотом, и он даже не говорит, занимают ли они память или нет, поэтому он не может сказать, как получить свой размер.
Как получить ссылочный размер:. Поскольку все ссылки на компиляторы реализуются с помощью постоянных указателей и они занимают память, есть способ узнать их размер.
class A_ref
{A& ref;}
sizeof(A_ref);
Ответ 3
Не особенно важно знать, сколько хранилищ требует эта ссылка, только изменение требований к хранилищу, вызванное добавлением ссылки. И вы можете определить:
struct with
{
char c;
T& ref;
};
struct without
{
char c;
};
return sizeof (with) - sizeof (without);