Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 02.02.2019, 17:43   #1
New man
Форумчанин
 
Регистрация: 24.01.2011
Сообщений: 774
По умолчанию Насколько хороша мысль принимать только rvalue аргументы?

В общем, я задумался, насколько хорошая мысль создавать публичный интерфейс только на move методах, если нам нужно как-то преобразовывать некий массив байт, например.

Вот пример:
Код:
#include <iostream>
#include <string>
#include <algorithm>

bool keep(char c) noexcept
{
     return c !='\n' && c!='\t' && c!=' ';
}

std::string simplify_json(std::string&& origin) noexcept
{
    auto end = std::copy_if(origin.begin(), origin.end(), origin.begin(), keep);
    origin.resize(end - origin.begin());
    return std::move(origin);
}

int main()
{
    using str = std::string;
    std::string json(
        str("{\n") + 
   str("\"firstName\": \"Ivan\",\n") + 
   str("\"lastName\": \"Ivanov\"\n") +
        str("}")
        );
    
    // Invalid, compile error
   //std::cout<<simplify_json(json); 
    
    // User suppose that he will need original json, so it decide to copy
    std::cout<<simplify_json(str(json))<<std::endl;
    
    // User sure that he don't need original json anymore
    std::cout<<simplify_json(std::move(json))<<std::endl;
}
Соответственно, уже пользователь решает, нужно ли ему копировать данные или сделать move.

Стандартно в таких преобразователях я передаю аргумент по константной ссылке, за счёт чего есть гарантия, что оригинал не поменяется внутри функции, но появляется такой недостаток, как лишнее выделение памяти внутри функции, за счёт чего она ещё и теряет модификатор noexcept.
Пример:
Код:
std::string simplify_json2(const std::string& origin)
{
    std::string res;
    res.resize(origin.size());
    auto end = std::copy_if(origin.begin(), origin.end(), res.begin(), keep);
    res.resize(end - res.begin());
    return res;
}
Соответственно, видны преимущества move варианта.

Но всё это можно так же сделать так:
Код:
std::string simplify_json3(std::string origin) noexcept
{
    auto end = std::copy_if(origin.begin(), origin.end(), origin.begin(), keep);
    origin.resize(end - origin.begin());
    return std::move(origin);
}
В таком случае юзер может сделать оба варианта:
Код:
std::cout<<simplify_json(json); 
std::cout<<simplify_json(std::move(json));
И работать они будут. Но так как мы никак не вынуждаем пользователя думать о том, что он передаёт в функцию, он скорее всего будет выбирать первый способ с копированием, даже если была возможность передать с помощью move.

В итоге, у меня два вопроса:
1) стоит ли писать вариант только с move вместо варианта передачи просто по значению, побуждая пользователя задумываться, надо ли ему сохранять старое значение или нет?
2) может ли компилятор провести оптимизацию сам и вызывать move конструктор вместо конструктора копирования в случаях:
Код:
    std::string origin = ....;
    std::string simplified = simplify_json(origin); // Будет ли параметр создан перемещением или копированием?
    // далее origin нигде не используется, а только simplified
    ....
a.k.a. Angelicos Phosphoros
Мой сайт
New man вне форума Ответить с цитированием
Старый 03.02.2019, 09:54   #2
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,493
По умолчанию

Цитата:
Сообщение от New man Посмотреть сообщение
Будет ли параметр создан перемещением или копированием?
Параметр не будет создан вообще - будет передана ссылка на уже созданный объект.
Сделайте две функции - одна с & другая с &&.
Первая будет возвращать ссылку на свой параметр, вторая буде возвращать строку, но будет делать move.
Вторая функция просто будет вызывать первую.
А дальше уже делайте бенчмарки.
waleri вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
натолкни на мысль FIFAPES Общие вопросы C/C++ 31 03.10.2014 16:52
Натолкните на мысль! Niklitel Помощь студентам 2 05.01.2014 15:17
с++ командная строка, Вывести все нечисловые аргументы, но выводит все аргументы чего-то, nati_94 Помощь студентам 8 03.03.2013 19:23
Натолкните на мысль Rebelition Общие вопросы Delphi 6 30.10.2012 14:42
Дайте мысль) jawa250t Общие вопросы Delphi 4 09.02.2011 18:02