rvalue ссылки прерываются при глубоком возврате - PullRequest
0 голосов
/ 07 января 2011

Я столкнулся с проблемой при передаче возвращенных ссылок rvalue с глубины более 1.

struct Data {
 std :: vector <int> data;
 Data () {
  data .push_back (1);
 };

 Data (Data && d)
 : data (std :: move (d .data))
 {}
};

Data && foo () {
 Data d;
 return std :: move (d);
}

Data && bar () {
 return std :: move (foo ()); // Crashes in autogenerated code
}

Data && baz () {
 return foo (); // Crashes in Data move constructor.
}

Data && bop () {
 Data d = foo ();
    return std :: move (d); // Crashes in autogenerated code.
}

int main () {
 Data d_foo = foo (); // This is fine.
 Data d_bar = bar (); // Crash.
 Data d_bar = baz (); // Crash.
 Data d_bop = bop (); // Crash.
}

Я думаю, что std :: vector освобождается дважды.Я использую g ++ (Ubuntu / Linaro 4.4.4-14ubuntu5) 4.4.5

Работает ли вышеуказанный код для вас?Я что-то не так делаю или есть ошибка в библиотеке или компиляторе?

Если (небесный форфенд) это компилятор (есть другие известные ошибки C ++ 0x в gcc), может кто-нибудь сказать мне, еслиЕсть ли apt-безопасный способ обновления или исправления gcc в Ubuntu?Я пробовал раньше, но попал в клубок неподдерживаемых пакетов.

Большое спасибо.

Ответы [ 3 ]

6 голосов
/ 07 января 2011

Редко имеет смысл возвращать rvalue ссылки из функции (исключение std :: move), потому что ссылка предположительно была привязана к временному объекту в стеке, как в вашем случае, и когда вы его возвращали, объект исчез .

Edit:

Data && foo () {
 Data d;
 return std :: move (d);
}

d уничтожается при выходе из области видимости, поэтому вы возвращаете висячую ссылку.

5 голосов
/ 07 января 2011

Вы не возвращаете ссылку на rvalue, вы возвращаете значение, которое затем вызывается вызывающей стороной как ссылка как значение. Вы должны просто иметь Data foo(), а не Data&& foo(). Тот факт, что любое из этих произведений является чисто совпадением, поскольку это неопределенное поведение.

0 голосов
/ 08 января 2011

Вы не можете ожидать ничего хорошего от возврата && локальному объекту так же, как от возврата обычной ссылки / указателя на локальный объект.

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

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

...