Пример кода, который неправильно пытается переместить ссылку - PullRequest
3 голосов
/ 30 ноября 2010

Насколько я понимаю, C ++ не позволяет вам переместить ссылку. Другими словами, вы не можете изменить объект, на который ссылается ссылка. Это похоже на постоянный указатель в этом отношении (например, int* const a = 3;).

В каком-то коде, который я посмотрел сегодня, я увидел следующее:

CMyObject& object = ObjectA().myObject();
// ...
object = ObjectB().myObject();

Сразу же прозвенели мои сигналы тревоги в последней строке кода выше. Разве код не пытался переназначить ссылку? И все же код скомпилирован.

Затем я понял, что код выполняет простой вызов оператора присваивания (т. Е. operator=) для переназначения внутреннего объекта ObjectA внутреннему объекту ObjectB. Ссылка object все еще ссылается на ObjectA, просто содержимое ObjectA теперь соответствует содержимому ObjectB.

Насколько я понимаю, компилятор всегда будет генерировать оператор присваивания по умолчанию, если вы его не предоставите, что делает поверхностную копию (аналогично конструктору копирования по умолчанию).

Поскольку ссылка набирается (как и базовый объект, на который она ссылается), это не значит, что мы всегда будем вызывать оператор присваивания при попытке переназначить ссылку, тем самым предотвращая жалобу компилятора

Я ломал голову, пытаясь придумать недопустимую строку кода, которая неправильно попытается переместить ссылку, чтобы компилятор жаловался.

Может кто-нибудь указать мне пример такого кода?

Ответы [ 4 ]

2 голосов
/ 30 ноября 2010

Вы не можете "переустановить" ссылку, потому что это синтаксически невозможно.Используемая вами ссылочная переменная, которая ссылается на объект, использует ту же семантику, что и была объектной (не ссылочной) переменной.

1 голос
/ 30 ноября 2010

Я ломал голову, пытаясь придумать недопустимую строку кода, которая неправильно попытается переместить ссылку, чтобы компилятор жаловался.*

Непосвященный может ожидать, что последняя строка будет перенесена с r на j, но вместо этого назначение на i не выполняется.

1 голос
/ 30 ноября 2010

Насколько я понимаю, компилятор всегда будет генерировать оператор присваивания по умолчанию, если вы его не предоставите, который выполняет поверхностное копирование (аналогично конструктору копирования по умолчанию).

Поскольку ссылканабирается (точно так же, как базовый объект, на который он ссылается), не означает ли это, что мы всегда будем вызывать оператор присваивания при попытке переназначить ссылку, тем самым предотвращая жалобу компилятора на это?

Это не совсем так.Неявное копирование (присваивание) выполняет копирование по элементам (не обязательно поверхностное), и компилятор не позволяет неявно происходить плохим вещам со ссылочными элементами.

class X
{
    int& ref;
public:
    X(int& r): ref(r) {}
};

int main()
{
    int i;
    X a(i), b(i);
    a = b;
}
1 голос
/ 30 ноября 2010

Вы не можете написать переносимый код C ++ для повторного размещения ссылки ... компилятор отслеживает, куда ссылается ссылка, и не позволяет ее изменять.Это своего рода псевдоним для всего, на что он ссылается, и в некоторых случаях ссылочное значение может быть включено непосредственно в код во время компиляции.В некоторых реализациях, где конкретная ссылка хранится в форме указателя и иногда просматривается во время выполнения, вы можете использовать приведение к переинтерпретации для перезаписи ее указателем на другой объект, но поведениеполностью неопределен и ненадежен.Сколько бы это ни стоило (практически ничего, но, возможно, немного помощи в понимании вероятной реализации), это может выглядеть примерно так:

struct X
{
    Y& y_;
    X(Y& y) : y_(y) { }
};

...
X x(y1);
*reinterpret_cast<Y**>(&x) = &y2;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...