Re[3]: const в аргументах методов
От: _hum_ Беларусь  
Дата: 05.04.16 13:16
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Здравствуйте, __kot2, Вы писали:


Y>>>1. Насколько оправдано написание const спецификатора при передаче в метод параметров по значению? Может в этом нет смысла, ведь идет копирование?

__>>а в чем смысл передачи по значению тут? надо по const &. это, конечно, про string.

BFE>Согласно "последнему постановлению ВЦСПС" std::string надо передавать по значению (и без const) в том случае, если внутри функции эту строку подлежит сохранить в другую переменную, например, в член класса:


BFE>
BFE>class Drink
BFE>{
BFE>  public:
BFE>    void SetName(std::string strName)
BFE>    {
BFE>      m_name = std::move(strName);
BFE>    } 
BFE>  private:
BFE>     std::string m_name;
BFE>};
BFE>


странно, ведь все равно ж strName в стек будет засунут. или надо рассчитывать на оптимизацию компилятора?
Re[4]: const в аргументах методов
От: B0FEE664  
Дата: 05.04.16 13:54
Оценка:
Здравствуйте, _hum_, Вы писали:

BFE>>Согласно "последнему постановлению ВЦСПС" std::string надо передавать по значению (и без const) в том случае, если внутри функции эту строку подлежит сохранить в другую переменную, например, в член класса:


BFE>>
BFE>>class Drink
BFE>>{
BFE>>  public:
BFE>>    void SetName(std::string strName)
BFE>>    {
BFE>>      m_name = std::move(strName);
BFE>>    } 
BFE>>  private:
BFE>>     std::string m_name;
BFE>>};
BFE>>


__>странно, ведь все равно ж strName в стек будет засунут. или надо рассчитывать на оптимизацию компилятора?

Да, можно рассчитывать, так как функция — inline, но дело тут не в этом, а в том, что у std::string есть часть лежащая в хипе, которую так или иначе надо скопировать один раз. Если есть вызов типа такого:
  Drink d;
  d.SetName("asdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdf");

, то для константной ссылки будет два копирования, а для вышеприведённой функции — одно. Однако же, если копирование значения параметра внутри функции не нужно, то, теоретически, выгодно передавать константную ссылку, но при этом стоит учесть это
Автор: watchmaker
Дата: 04.04.16
.
И каждый день — без права на ошибку...
Re[5]: const в аргументах методов
От: _hum_ Беларусь  
Дата: 05.04.16 14:52
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Здравствуйте, _hum_, Вы писали:


BFE>>>Согласно "последнему постановлению ВЦСПС" std::string надо передавать по значению (и без const) в том случае, если внутри функции эту строку подлежит сохранить в другую переменную, например, в член класса:


BFE>>>
BFE>>>class Drink
BFE>>>{
BFE>>>  public:
BFE>>>    void SetName(std::string strName)
BFE>>>    {
BFE>>>      m_name = std::move(strName);
BFE>>>    } 
BFE>>>  private:
BFE>>>     std::string m_name;
BFE>>>};
BFE>>>


__>>странно, ведь все равно ж strName в стек будет засунут. или надо рассчитывать на оптимизацию компилятора?

BFE>Да, можно рассчитывать, так как функция — inline, но дело тут не в этом, а в том, что у std::string есть часть лежащая в хипе, которую так или иначе надо скопировать один раз. Если есть вызов типа такого:
BFE>
BFE>  Drink d;
BFE>  d.SetName("asdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdf");
BFE>

BFE>, то для константной ссылки будет два копирования, а для вышеприведённой функции — одно.

а почему два-то, если речь о
void SetName(const std::string& strName)
{
   m_name = strName;
}

?

А еще впорос — для случая передачи по константному значению компилятор сможет выполнить оптимизацию и не копировать это константное значение в стек?
void SetName(const std::string strName)
{
   m_name = strName;
}
Re[2]: const в аргументах методов
От: Tessi  
Дата: 05.04.16 15:41
Оценка:
Здравствуйте, tstalker, Вы писали:

T>Если нестатический метод класса вызывается от имени объекта класса, можно не переживать.


иногда и в статический можно для удобства использования, но обычно это понятно по объявлению функции или в ее описании

namespace Tools
{
std::string & Trim (std::string & str)
{
     // trim 'str' here
     return str;
}
void Trim (std::string & str)
{
     // trim 'str' here
}
}

std::string str = "  1234  ";
std::cout << Tools::Trim (str);
Re: const в аргументах методов
От: Videoman Россия https://hts.tv/
Дата: 05.04.16 16:05
Оценка:
Здравствуйте, yaser, Вы писали:

Y>Собственно 2 вопроса

Y>1. Насколько оправдано написание const спецификатора при передаче в метод параметров по значению? Может в этом нет смысла, ведь идет копирование?
По поводу этого пункта уже выше все детально разобрали.

Y>2. Насколько хорошо возвращать ссылку на члены класса? Может быть история что ссылка осталась, а класса нет. Может лучше отдавать по значению?

Плохо. На практике так делать не стоит, если только профайлер не показал что здесь узкое место. С точки зрения дизайна, это, почти, нарушение инкапсуляции, т.к. говорит что где-то там, внутри, есть std::string. Если время жизни класса планируется долгим, то при его дальнейшей модификации, возврат по ссылке может привести к проблемам с реализацией. Особенно осторожно нужно относиться к возвратам по ссылке, если метод виртуальный и класс планирует быть базовым для других или входить в иерархию наследования.
Отредактировано 06.04.2016 10:23 Videoman . Предыдущая версия . Еще …
Отредактировано 05.04.2016 17:37 Videoman . Предыдущая версия .
Re[6]: const в аргументах методов
От: B0FEE664  
Дата: 05.04.16 16:13
Оценка: 1 (1)
Здравствуйте, _hum_, Вы писали:

BFE>>Да, можно рассчитывать, так как функция — inline, но дело тут не в этом, а в том, что у std::string есть часть лежащая в хипе, которую так или иначе надо скопировать один раз. Если есть вызов типа такого:

BFE>>
BFE>>  Drink d;
BFE>>  d.SetName("asdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdf");
BFE>>

BFE>>, то для константной ссылки будет два копирования, а для вышеприведённой функции — одно.

__>а почему два-то, если речь о

__>
__>void SetName(const std::string& strName)
__>{
__>   m_name = strName;
__>} 
__>

__>?
Первый в конструкторе std::string, в strName;
второй при присваивании в m_name.

__>А еще впорос — для случая передачи по константному значению компилятор сможет выполнить оптимизацию и не копировать это константное значение в стек?

__>
__>void SetName(const std::string strName)
__>{
__>   m_name = strName;
__>} 
__>

Этого я не знаю.
И каждый день — без права на ошибку...
Re[3]: const в аргументах методов
От: __kot2  
Дата: 05.04.16 16:13
Оценка:
Здравствуйте, Erop, Вы писали:
E>Зачем? Всё равно же решение хранить копию или ссылку принимают снаружи?
ну вот допустим у нас есть ф-ия конкатенации строк
у нас есть два варианта
ф-ия
string plus(const string &a, const string &b) — которая создает новую строку и возвращает ее
string &plus(string &a, const string &b) — которая модифицирует a и возвращает а

первый вариант ведет себя более ожидаемо, можно просто по запаре не заметить, что второй модифицирует a, второй — сильно быстрее на большом кол-ве таких операций
как бы идеологически удобнее именно первый вариант. мы не модифицируем обьект, а создаем новый. по крайней мере это даже потокобезопасно.
так и куче ф-ий идеологически правильнее будет сконструирвать какой-то временный обьект и вернуть его. но в этом случае нам, сообв-но нельзя хранить его по ссылке.

бывает, что нам реально нужны указатели на обьекты, а не копии
типа string &find(...)

но в этом случае я лично предпочитаю не мучаться раздумиями о владениях и временах жизни обьектов и не мучать этим коллег, а перейти к смартпойнтерам вместо референсов, что избавит от ненужных копирований обьектов, и при этом сами смартпойнтеры, конечно, возвращатся по значению
string_ptr find(...)
Re[4]: const в аргументах методов
От: Erop Россия  
Дата: 05.04.16 19:00
Оценка:
Здравствуйте, __kot2, Вы писали:

__>string plus(const string &a, const string &b) — которая создает новую строку и возвращает ее

__>string &plus(string &a, const string &b) — которая модифицирует a и возвращает а

__>первый вариант ведет себя более ожидаемо, можно просто по запаре не заметить, что второй модифицирует a, второй — сильно быстрее на большом кол-ве таких операций

__>как бы идеологически удобнее именно первый вариант. мы не модифицируем обьект, а создаем новый. по крайней мере это даже потокобезопасно.
1) Это вопрос не про то, что возвращать, а про то, что менять.
2) второе очень популярно, просто обычно эту фнкцию называют operator+=

__>так и куче ф-ий идеологически правильнее будет сконструирвать какой-то временный обьект и вернуть его. но в этом случае нам, сообв-но нельзя хранить его по ссылке.


Нет, когда мы возвращаем НОВЫЙ объект, то выбора как возвращать нет.
Вопрос стоит только тогда, когда мы можем выбрать что возвращать, ссылку или копию...
скажем так:
template<typename T>
T& select( bool takeLeft, T& left, T& right ) { return takeLeft ? left : right; }


__>но в этом случае я лично предпочитаю не мучаться раздумиями о владениях и временах жизни обьектов и не мучать этим коллег, а перейти к смартпойнтерам вместо референсов, что избавит от ненужных копирований обьектов, и при этом сами смартпойнтеры, конечно, возвращатся по значению

То есть какой-нибудь метод GetName у тебя возвращает смартпоинтер на строку?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[5]: const в аргументах методов
От: __kot2  
Дата: 05.04.16 19:19
Оценка:
Здравствуйте, Erop, Вы писали:
E>1) Это вопрос не про то, что возвращать, а про то, что менять.
E>2) второе очень популярно, просто обычно эту фнкцию называют operator+=
я просто пример показал двух разных поведений. когда у нас результат — во временном обьекте. или мы результат можем и на месте организовать

E>То есть какой-нибудь метод GetName у тебя возвращает смартпоинтер на строку?

я вообще не люблю геттеры-сеттеры. использую только если прямо ну никак нельзя без них
поэтому вместо сеттера у меня скорее всего будет создание нового обьекта

типа вместо
void marry(husband, wife)
{
wife.set_last_name(husband.last_name)
}

будет что-то в духе

Person married_wife(husband, wife)
{
return person(wife.first_name, husband.last_name)
}

а вместо геттеров я предпочитаю иметь иммутабельные поля (или в С++ const ссылки-указатели на обьекты) и спокойно не парясь обращаться к ним напрямую

const Person &wife;

cout << wife.last_name << endl; — нормалек
Re[6]: const в аргументах методов
От: Erop Россия  
Дата: 05.04.16 19:30
Оценка:
Здравствуйте, __kot2, Вы писали:

__>я просто пример показал двух разных поведений. когда у нас результат — во временном обьекте. или мы результат можем и на месте организовать


Тем не менее, operator+ и operator+= обычно считаются РАЗНЫМИ функциями...

E>>То есть какой-нибудь метод GetName у тебя возвращает смартпоинтер на строку?

__>я вообще не люблю геттеры-сеттеры. использую только если прямо ну никак нельзя без них

Ну, вот, например CFile::GetName что должен возвращать? Смартпоинтер на строку?

__>а вместо геттеров я предпочитаю иметь иммутабельные поля (или в С++ const ссылки-указатели на обьекты) и спокойно не парясь обращаться к ним напрямую


__>const Person &wife;


__>cout << wife.last_name << endl; — нормалек


IMHO, это не всегда удобно, ну и сильно выходит за тему что возвращать...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[7]: const в аргументах методов
От: __kot2  
Дата: 05.04.16 19:44
Оценка: :)
Здравствуйте, Erop, Вы писали:
E>Тем не менее, operator+ и operator+= обычно считаются РАЗНЫМИ функциями...
да кто же спорит. но не будете же вы для всего писать два варианта — на месте и с созданием копии.
типа, например, реверс строки. вы всегда можете с помощью += реализовать + и наоборот (обычно первое), но не будете же вы везде дублировать одни и те же ф-ии.
проще писать и подерживать код, который обьекты не модифицирует никогда. в этом и есть смысл фукнционального программирования. но совсем не обязательно писать на хаскеле, чтобы пользоваться плюшками такого подхода

E>Ну, вот, например CFile::GetName что должен возвращать? Смартпоинтер на строку?

вообще такого метода у файла быть не должно

__>>а вместо геттеров я предпочитаю иметь иммутабельные поля (или в С++ const ссылки-указатели на обьекты) и спокойно не парясь обращаться к ним напрямую

__>>const Person &wife;
__>>cout << wife.last_name << endl; — нормалек
E>IMHO, это не всегда удобно, ну и сильно выходит за тему что возвращать...
когда я давно начинал писать я писал миллионами эти геттеры. потом задолбался. это просто лишняя работа, не несущая никаких бенефитов. переделать доступ к члену на обращение к геттеру — фигня вопрос. конечно, не для каких-нибудь публичных библиотек, но я их никогда и не писал
Re[8]: const в аргументах методов
От: Erop Россия  
Дата: 05.04.16 20:20
Оценка:
Здравствуйте, __kot2, Вы писали:

__>проще писать и подерживать код, который обьекты не модифицирует никогда. в этом и есть смысл фукнционального программирования. но совсем не обязательно писать на хаскеле, чтобы пользоваться плюшками такого подхода

На С++ сильно не все программы в функциональном стиле пишутся...
Ну и часто дорого просто... Ну, например функциональная версия CART насколько дороже будет по памяти?

E>>Ну, вот, например CFile::GetName что должен возвращать? Смартпоинтер на строку?

__>вообще такого метода у файла быть не должно
Почему?

__>когда я давно начинал писать я писал миллионами эти геттеры. потом задолбался. это просто лишняя работа, не несущая никаких бенефитов. переделать доступ к члену на обращение к геттеру — фигня вопрос. конечно, не для каких-нибудь публичных библиотек, но я их никогда и не писал


Ну я тоже гетеры не люблю. Но есть же нетривиальные гетеры...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[9]: const в аргументах методов
От: __kot2  
Дата: 05.04.16 20:48
Оценка:
Здравствуйте, Erop, Вы писали:
__>>проще писать и подерживать код, который обьекты не модифицирует никогда. в этом и есть смысл фукнционального программирования. но совсем не обязательно писать на хаскеле, чтобы пользоваться плюшками такого подхода
E>На С++ сильно не все программы в функциональном стиле пишутся...
E>Ну и часто дорого просто... Ну, например функциональная версия CART насколько дороже будет по памяти?
разумеется, допустим, нейросеть в ф-ом стиле написанная вообще никому не нужна будет
поэтому на ф-ых языках никто сильно и не пишет. просто в большинстве случаев, типа простейшей работы с юзерами, бд, удобнее когда код в ф-ом стиле.

вместо
user.set_name(new_name)
{
validate()
commit()
notify()
}

user.set_age(new_age)
{
validate()
commit()
notify()
}


у нас будет

new_user = new user(new_name, old_age) или new_user = new user(old_name, new_age)

и controller.replace(old_user, new_user)

который уже будет делать
{
validate()
commit()
notify()
}

E>>>Ну, вот, например CFile::GetName что должен возвращать? Смартпоинтер на строку?

__>>вообще такого метода у файла быть не должно
E>Почему?
скорее вопрос стоит — а зачем он там нужен?
может ли имя файла измениться за время открытия файла?
бывают ли файлы безымянные?
а нет ли ньюансов с симлинками?
а нет ли случаев когда это имя укоротится до формата 8.3 для совместимости с чем-то? или юникодные символы не заменятся чем-то?

я вот лично просто не знаю ответов на эти вопросы, но подозреваю, что там скрываются тонны геморроя. и ради чего это? мы что, не знаем какой файл открываем при его открытии? зачем нам об этом задним числом узнавать?

E>Ну я тоже гетеры не люблю. Но есть же нетривиальные гетеры...

бывают еще и констукторы-деструкторы непритивиальные, который в логи пишут, уникальные id генерируют или еще какие сайд-эффекты. именно поэтому проще иметь смартпойнтер во многих случаях. так и пришли люди к java — C#. хотя никто не мешает в том же стиле писать на С++
Re[10]: const в аргументах методов
От: Erop Россия  
Дата: 05.04.16 21:03
Оценка:
Здравствуйте, __kot2, Вы писали:

__>поэтому на ф-ых языках никто сильно и не пишет. просто в большинстве случаев, типа простейшей работы с юзерами, бд, удобнее когда код в ф-ом стиле.

Ну это от области оч. зависит. Если перфомансом занята БД, то не ясно на кой вообще вокруг с С++ прыгать...

__>new_user = new user(new_name, old_age) или new_user = new user(old_name, new_age)


А если аттрибутов юзера примерно 100500, и они имеют свойство добавляться иногда?

E>>Почему?

__>скорее вопрос стоит — а зачем он там нужен?
__>я вот лично просто не знаю ответов на эти вопросы, но подозреваю, что там скрываются тонны геморроя. и ради чего это? мы что, не знаем какой файл открываем при его открытии? зачем нам об этом задним числом узнавать?
Ну, например, читаем мы из файла данные, и тут находим ошибку, хотим кинуть исключение с диагностикой, как его параметризовать указанием на то, в каком конкретно файле ошибка?



E>>Ну я тоже гетеры не люблю. Но есть же нетривиальные гетеры...

__>бывают еще и констукторы-деструкторы непритивиальные,
Это ты про другое... Например, бывают виртуальные функции GetЧегоНибудь...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[11]: const в аргументах методов
От: __kot2  
Дата: 06.04.16 01:59
Оценка:
Здравствуйте, Erop, Вы писали:
E>А если аттрибутов юзера примерно 100500, и они имеют свойство добавляться иногда?
сгруппировать в отдельные классы, коих будет опять же, только несколько. наверное еще какие-то варианты есть.

E>Ну, например, читаем мы из файла данные, и тут находим ошибку, хотим кинуть исключение с диагностикой, как его параметризовать указанием на то, в каком конкретно файле ошибка?

это если мы exit() хотим сделать на месте, хотелось бы всю инфу протащить. а так файл же сам по себе не бывает, есть обвязка, которая знает что это за файл и обрабатывает разные ситуации. надо просто кинуть исключение наверх, что прочитать не можем, а уж что не можем — знают наверну

E>>>Ну я тоже гетеры не люблю. Но есть же нетривиальные гетеры...

__>>бывают еще и констукторы-деструкторы непритивиальные,
E>Это ты про другое... Например, бывают виртуальные функции GetЧегоНибудь...
бывает. убрать поле в приватные, заменить обращение к полю на вызов ф-ии в тех местах, где это происходит — не вижу никаких проблем
Re[12]: const в аргументах методов
От: Erop Россия  
Дата: 06.04.16 02:06
Оценка:
Здравствуйте, __kot2, Вы писали:

__>это если мы exit() хотим сделать на месте, хотелось бы всю инфу протащить. а так файл же сам по себе не бывает, есть обвязка, которая знает что это за файл и обрабатывает разные ситуации. надо просто кинуть исключение наверх, что прочитать не можем, а уж что не можем — знают наверну


Это же неудобно. Вот прикинь, я дал команду "открыть базу данных", а она в ответ плюётся исключением "повреждён файл такой-то". Так удобно. А если мне везде по стеку надо исключения обрабатывать и переформатировать, то я точно где-то ошибусь, это трудно тестировать и это всё точно лишняя работа. Намного лучше уметь у файла спросить имя...
Тем более, что это не проблема...

__>бывает. убрать поле в приватные, заменить обращение к полю на вызов ф-ии в тех местах, где это происходит — не вижу никаких проблем


Если не помнишь, мы обсуждаем что возвращать: копию или ссылку
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[13]: const в аргументах методов
От: __kot2  
Дата: 06.04.16 02:22
Оценка:
Здравствуйте, Erop, Вы писали:
E>Это же неудобно. Вот прикинь, я дал команду "открыть базу данных", а она в ответ плюётся исключением "повреждён файл такой-то". Так удобно. А если мне везде по стеку надо исключения обрабатывать и переформатировать, то я точно где-то ошибусь, это трудно тестировать и это всё точно лишняя работа. Намного лучше уметь у файла спросить имя...
E>Тем более, что это не проблема...
я даже псевдокод этого представить не могу
типа

open_db("filename")

и ... что, хочется чтобы что?

__>>бывает. убрать поле в приватные, заменить обращение к полю на вызов ф-ии в тех местах, где это происходит — не вижу никаких проблем

E>Если не помнишь, мы обсуждаем что возвращать: копию или ссылку
копию. если обьект большой и есть шанс просаживания скорости из-за лишних копирований — смартпойнтер на него.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.