Невозможно инициализировать неконстантную ссылку из конвертируемого типа - PullRequest
3 голосов
/ 25 марта 2010

Я не могу инициализировать неконстантную ссылку на тип T1 из конвертируемого типа T2. Тем не менее, я могу со ссылкой const .

long l;
const long long &const_ref = l; // fine
long long &ref = l;             // error: invalid initialization of reference of
                                // type 'long long int&' from expression of type
                                // 'long int'

Большинство проблем, с которыми я столкнулся, были связаны с r-значениями, которые нельзя присвоить неконстантной ссылке. Это не тот случай - кто-то может объяснить? Спасибо.

Ответы [ 4 ]

7 голосов
/ 25 марта 2010

Целочисленное продвижение приводит к значению. long может быть повышен до long long, а затем он привязывается к константной ссылке. Так же, как если бы вы сделали:

typedef long long type;
const type& x = type(l); // temporary!

Наоборот, rvalue, как вы знаете, не может быть привязан к неконстантной ссылке. (В конце концов, нет фактического long long, на который можно сослаться.)

1 голос
/ 25 марта 2010

long long необязательно имеет размер, равный long, и может даже использовать совершенно другое внутреннее представление. Поэтому вы не можете привязать неконстантную ссылку к long к объекту типа long long или наоборот. Стандарт запрещает это, и ваш компилятор не допустит этого.

Вы можете удивиться тому же фрагменту кода:

long a = 0; 
long long b = 0;

a = b; // works!

long *pa = 0;
long long *pb = pa;

Последняя инициализация не будет работать. То, что тип может быть преобразован в другой, не означает, что другой тип, который объединяет один из них, может быть преобразован в третий тип, который соединяет другой. Аналогично для следующего случая

struct A { long i; };
struct B { long long i; };

A a;
B b = a; // fail!

В этом случае A и B каждое составляет типы long и long long соответственно, так же, как long& и long long& составляют эти типы. Однако они не будут конвертируемыми друг в друга только из-за этого факта. Другие правила применяются.

Если ссылка на const, создается временный объект правильного типа, и ссылка затем привязывается к этому объекту.

0 голосов
/ 25 марта 2010

Давайте предположим, что это возможно:

 long long &ref = l; 

Это означает, что позже в коде вы можете изменить значение, на которое ссылается ref, на значение, которое больше, чем может содержать тип long, но нормально для long long. Практически это означает, что вы перезаписываете дополнительные байты памяти, которые могут использоваться различными переменными с непредсказуемыми результатами.

0 голосов
/ 25 марта 2010

Я не юрист по стандартам, но думаю, что это потому, что long long шире, чем long. Ссылка на const разрешена, потому что вы не будете изменять значение l. Обычная ссылка может привести к слишком большому для l присваиванию, поэтому компилятор этого не допустит.

...