От новичка до гуру: Курсы программирования на CyberDuff

Зачем бросать локальную переменную, вызывает конструктор движений?

Недавно я «поиграл» с rvalue, чтобы понять их поведение. Большинство результатов меня не удивило, но потом я увидел, что если я бросаю локальную переменную, вызывается конструктор перемещения.

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

Однако в следующем коде ни одно из этих условий не выполняется, и моя переменная все еще перемещается (по крайней мере, в g++ 4.7.3).

Почему это?

#include <iostream>
#include <string>
using namespace std;

int main() {
    string s="blabla";
    try {
        throw s;
    }
    catch(...) {
        cout<<"Exception!\n";
    }
    cout<<s; //prints nothing
}


Ответы:


1

В данном случае это, вероятно, ошибка компилятора, потому что на выброшенную (и перемещенную) переменную ссылаются впоследствии.

В общем случае вызов перемещения на throw концептуально аналогичен перемещению на return. Хорошо вызывать перемещение автоматически, когда известно, что на переменную нельзя ссылаться после заданной точки (throw или return).

05.06.2013

2

Стандарт С++ говорит (15.1.3):

Throwing an exception copy-initializes (8.5, 12.8) a temporary object, called the exception object. The temporary is an lvalue and is used to initialize the variable named in the matching handler (15.3).

Этот абзац может быть уместным и здесь (12.8.31):

When certain criteria are met, an implementation is allowed to omit the copy/move construction of a class object, even if the constructor selected for the copy/move operation and/or the destructor for the object have side effects. In such cases, the implementation treats the source and target of the omitted copy/move operation as simply two different ways of referring to the same object, and the destruction of that object occurs at the later of the times when the two objects would have been destroyed without the optimization. This elision of copy/move operations, called copy elision, is permitted in the following circumstances (which may be combined to eliminate multiple copies):

(...)

in a throw-expression, when the operand is the name of a non-volatile automatic object (other than a function or catch-clause parameter) whose scope does not extend beyond the end of the innermost enclosing try-block (if there is one), the copy/move operation from the operand to the exception object (15.1) can be omitted by constructing the automatic object directly into the exception object

Проверено в Visual Studio 2012, эффект:

Exception!
blabla

Это действительно похоже на ошибку в GCC.

05.06.2013
  • Если это так, компилятору не разрешено вызывать конструктор перемещения, даже если throw не находится внутри блока try? 05.06.2013
  • @asaelr: Из обновленной цитаты кажется, что объект, который нужно бросить, можно скопировать, переместить или даже построить на месте - так же, как и для возвращаемого значения. 05.06.2013
  • @asaelr Это так. Но в этом конкретном случае он неправильно вызывает move-ctor, потому что позже переменная используется вне try-блока. 05.06.2013
  • FWIW, VC++ реализует оптимизацию небольших строк (16 байт или около того...), но вывод, как и ожидалось, для более длинных строк. 05.06.2013
  • Его область действия ДЕЙСТВИТЕЛЬНО выходит за пределы самого внутреннего вложенного блока try. Строка была объявлена ​​до этого. 02.10.2017
  • Новые материалы

    Основы Spring: Bean-компоненты, контейнер и внедрение зависимостей
    Как лего может помочь нашему пониманию Когда мы начинаем использовать Spring, нам бросают много терминов, и может быть трудно понять, что они все означают. Итак, мы разберем основы и будем..

    Отслеживание состояния с течением времени с дифференцированием снимков
    Время от времени что-то происходит и революционизирует часть моего рабочего процесса разработки. Что-то более забавное вместо типичного утомительного и утомительного процесса разработки. В..

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

    Игра в прятки с данными
    Игра в прятки с данными Я хотел бы, чтобы вы сделали мне одолжение и ответили на следующие вопросы. Гуглить можно в любое время, здесь никто не забивается. Сколько регионов в Гане? А как..

    «Раскрытие математических рассуждений с помощью Microsoft MathPrompter и моделей больших языков»
    TL;DR: MathPrompter от Microsoft показывает, как использовать математические рассуждения с большими языковыми моделями; 4-этапный процесс для улучшения доверия и рассуждений в математических..

    Раскройте свой потенциал в области разработки мобильных приложений: Абсолютная бесплатная серия
    Глава 6: Работа в сети и выборка данных Глава 1: Введение в React Native Глава 2: Основы React Native Глава 3: Создание пользовательского интерфейса с помощью React Native Глава 4:..

    Все о кейсах: Camel, Snake, Kebab & Pascal
    В программировании вы сталкивались с ними при именовании переменной, класса или функции. Поддержание согласованности типов и стилей случаев делает ваш код более читабельным и облегчает совместную..