LINUX.ORG.RU

QString(const QString &) и noexcept

 ,


0

5

скажите, я правильно понимаю, что из-за «QString uses implicit sharing (copy-on-write) to reduce memory usage and to avoid the needless copying of data» функции-члены, которые копируют QString можно смело помечать как noexcept?

например

class MClass
{
    QString m_string;
public:
    MClass(const QString &string) noexcept : m_string{string} {}
}
★★★★★

Раз уж С++11 то возьми за правило все аргументы, которые собираешься копировать передавать по значению для всех типов у которых есть move constructor.

Ну и по теме: значние noexcept можно вычислять, тогда точно не ошибешься.

class MClass
{
    QString m_string;
public:
    MClass(QString input) noexcept(noexcept(m_string{std::move(input)}))
        : m_string{std::move(input)}
    {}
};
redbaron ★★
()

Конструктор QString(const QString &) не обещает noexcept. Но, используя CoW, можно реализовать небросающий конструктор. Так что формально ответ 'нет', но по факту скорее всего можно на это расчитывать.

mashina ★★★★★
()

В конструкторе копирования QString только инициализация указателя и вызов метода ref(), помеченного Q_DECL_NOTHROW. Ни то, ни другое не может выкинуть исключение. Стало быть, можешь помечать.

Только вот почему сам конструктор копирования QString не помечен как Q_DECL_NOTHROW?

NeXTSTEP ★★
()
Ответ на: комментарий от redbaron

Раз уж С++11 то возьми за правило все аргументы, которые собираешься копировать передавать по значению для всех типов у которых есть move constructor.

Наркоман штоле?

Pavval ★★★★★
()
Ответ на: комментарий от Pavval

С чего бы?

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

redbaron ★★
()
Ответ на: комментарий от redbaron

Если передавать в конструктор ссылку, то move-конструктор не сработает, так?

Нужно тогда явно определить недефолтный (из QString) конструктор с move-семантикой, разве нет?

Adonai ★★★
()
Ответ на: комментарий от Adonai

Нужно тогда явно определить недефолтный (из QString) конструктор с move-семантикой, разве нет?

Да, но это не решение вопроса с CoW. Для CoW move конструктор не подходит.

mashina ★★★★★
()
Ответ на: комментарий от Adonai

Если использовать «const QString&», то попробуй представить, что получится если передать туда rvalue:

  1. создать rvalue объект
  2. скопировать из него потроха в m_string

Если же «QString» аргумент (по значению) то:

  1. создать rvalue объект (за счет return value optimization он создастся один раз по адресу где его ожидает наш конструктор)
  2. переместить (== скопировать указатель) внутренности в точку назначения.

Теперь возможные случаи, если вызываем lvalue аргументом При этом, в случае передачи lvalue для «const QString&»:

  1. скопировать потроха в m_string

lvalue случай для «QString»:

  1. скопировать потроха в во временный объект
  2. переместить внутренности в точку назначения.

Т.е. в худшем случае мы вызовем лишний move конструктор у QString, что не страшно :)

redbaron ★★
()
Ответ на: комментарий от redbaron

которые собираешься копировать передавать по значению для всех типов у которых есть move constructor.

нахрена, если мне нужно копирование?

Stil ★★★★★
() автор топика
Ответ на: комментарий от NeXTSTEP

Только вот почему сам конструктор копирования QString не помечен как Q_DECL_NOTHROW?

это меня и смущает в половине классов Qt

Stil ★★★★★
() автор топика
Ответ на: комментарий от Stil

ты копирование и получишь, просто более эффективное, в случае если передаешь временные объекты.

Вообще в идеале надо делать для каждого параметра 2 варианта: «const QString&» и «QString&&» + std::move, тогда будет сгенерирован самый оптимальный код из всех возможных, но количество конструкторов тогда растет квадратично: для 3 аргументов надо будет создать 9 перегрузок".

redbaron ★★
()
Ответ на: комментарий от redbaron

мысль понял, но для CoW классов это таки не актуально (имхо, конечно), не думаю что передернуть ref/deref сильно долго

Stil ★★★★★
() автор топика
Последнее исправление: Stil (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.