Re[2]: Поймите и используйте STL
От: Abyx Россия  
Дата: 18.09.12 11:24
Оценка:
Здравствуйте, Шебеко Евгений, Вы писали:

ШЕ>std::hash_map<>,std::hash_set<>


нету таких классов в std

ШЕ>//предикат

ШЕ>struct human_pr
ШЕ>{
ШЕ> inline bool operator()(const human_t& a,const human_t& b) const
ШЕ> {
ШЕ> if(a.last_name!=b.last_name)return a.last_name<b.last_name;
ШЕ> return a.first_name<b.first_name;
ШЕ> }
ШЕ>};
ШЕ>


если С++03 — зачем функтор если достаточно функции
если С++ — должна быть лямбда.
In Zen We Trust
Re[2]: Книги
От: MasterZiv СССР  
Дата: 18.09.12 11:25
Оценка:
On 09/18/2012 02:56 PM, Шебеко Евгений wrote:

> "Андрей Александреску: Современное проектирование на С++" — книга скорее

> вредная, чем полезная.
> Она производит сильное впечатление, у читателя сразу случается приступ шаблонизма.
> Хотя сам Александреску призывает разумно использовать шаблоны и не заменять ими
> наследование.

+1. Очень всё правильно.
Posted via RSDN NNTP Server 2.1 beta
Re[2]: Resource Acquisition Is Initialization
От: Abyx Россия  
Дата: 18.09.12 11:27
Оценка: +1
Здравствуйте, Шебеко Евгений, Вы писали:

ШЕ>Для динамических объектов можно использовать смарт указатели. Например: shared_ptr (boost::shared_ptr, std::shared_ptr) или std::auto_ptr

std::auto_ptr устарел. в С++03 лучше использовать boost::scoped_ptr или boost::unique_ptr

ШЕ>Предпочтительнее использовать shared_ptr<>, т.к. внутри него есть счётчик ссылок, что позволяет его безопасно копировать и хранить в контейнерах.

ниразу не предпочтительнее. он потокобезопасный и потому очень медленный, так что предпочтительнее — std::unique_ptr.
к томуже в большинстве случаев общее владение объектом не нужно.
In Zen We Trust
Re[2]: Не используйте голые строки C
От: MasterZiv СССР  
Дата: 18.09.12 11:32
Оценка: +1 -1
On 09/18/2012 02:51 PM, Шебеко Евгений wrote:

> Вот такой код:

>
>
> char q[1024];
> strcpy(q,"select p.street from payers as p, pl_accounts as a where a.orgid=");
> strcat(q, vOrgID.at(lsOrganisation.GetCurSel()).GetString());
> strcat(q," and p.id=a.payerid group by p.street order by p.street;");
> if(!cur.Prepare(q))
>
>
>
> Должен выглядеть так:

Ещё очень удобно и правильно использовать вектора для таких временных буферов:

std::vector< char > q(1024);
strcpy(&q[0],"select p.street from payers as p, pl_accounts as a where a.orgid=");
strcat(&q[0], someVal);
strcat(&q[0]," and p.id=a.payerid group by p.street order by p.street;");

Также можно это использовать для временных буферов для вызова C API,
ну и конечно же в даном примере можно подтянуть и boost::printf и многое другое.
В современной версии стандартна так можно использовать и std::string вместо
std::vector.

Только один недостаток: лишняя нагрузка на хип и может быть лишная точка
синхронизации в многопоточных приложениях.
Posted via RSDN NNTP Server 2.1 beta
Re[4]: Стандарты программирования на С++
От: MasterZiv СССР  
Дата: 18.09.12 11:36
Оценка: +1
> Вопрос-то не в том, а в том, зачем нужны советы от Шебеко.

ПО-моему так всё очень правильно и здорово. Не важно, от кого советы, важно,
чтобы были правильные. А еси повторяются -- не страшно, лишний раз кто-то
прочитает -- хуже не будет.
Posted via RSDN NNTP Server 2.1 beta
Re[5]: Стандарты программирования на С++
От: igna Россия  
Дата: 18.09.12 11:39
Оценка: +1
Здравствуйте, MasterZiv, Вы писали:

MZ>ПО-моему так всё очень правильно и здорово. Не важно, от кого советы, важно,

MZ>чтобы были правильные. А еси повторяются -- не страшно, лишний раз кто-то
MZ>прочитает -- хуже не будет.

Да нет, просто в книге все собрано и ссылки на Мейерса, Саттера, Страуструпа и других, если кого какая тема заинтересовала и хочется поподробнее. И книга сама тонюсенькая, чуть больше 200 страниц.
Re[3]: Книги
От: igna Россия  
Дата: 18.09.12 11:44
Оценка: +2
Здравствуйте, MasterZiv, Вы писали:

>> Хотя сам Александреску призывает разумно использовать шаблоны и не заменять ими

>> наследование.

MZ>+1. Очень всё правильно.


Что правильно-то? Если нужен статический полиморфизм (времени компиляции), а не динамический (времени выполнения), то как раз нужно использовать шаблоны, а не наследование.
Re: TOP граблей С++ для новичков
От: Lorenzo_LAMAS  
Дата: 18.09.12 11:46
Оценка: :))) :))) :)
Здравствуйте, Шебеко Евгений, Вы писали:

ШЕ>Сейчас приходится собеседовать много новичков.

ШЕ>Заметил что ничего в жизни не меняется.
ШЕ>Даже люди с опытом работы в крупных наступают на те же грабли, на которые наступал я в своё время.

ШЕ>Хочу представить такие рекомендации новичкам в C++. Для того чтобы вы могли повысить свой уровень

ШЕ>ну и хотя бы лучше пройти собеседование.

ШЕ>Если кто желает что-то добавить — пожалуйста.

ШЕ>Только просьба придерживаться таких соглашений:

ШЕ>- Это должны быть грабли, на которые наступают регулярно.

ШЕ>- Краткое описание проблемы и методы её решение.
ШЕ>- Обяснение причин.
ШЕ>- Проверенный (скомпилированный) пример кода.


соседушко по офису, дебил и неряха, десятилетиями пишет код вида:

....
int * arr = new int[some_size];

if (laja)
   return;
...

delete [] arr;


Ошибка — тривиальная и дебильная, как и мой сосед: неиспользование РАИИ приводит к тому, что любой ресурс, требующий освобождения (с памятью — это самое простое)
у этого имбецила утекает в любой более/менее сложной функции, где есть какие-то вложенные блоки.

Спасает только статический анализатор, который заваливает этого ЛОШАРУ горами сообщений.
Ес-но, фикся, кретин плодит новое говно и получает по тупой харе от анализатора и т.д. — имя этому процессу — бесконечность.
Of course, the code must be complete enough to compile and link.
Re[3]: Resource Acquisition Is Initialization
От: igna Россия  
Дата: 18.09.12 11:47
Оценка: :))
Здравствуйте, Abyx, Вы писали:

ШЕ>>Для динамических объектов можно использовать смарт указатели. Например: shared_ptr (boost::shared_ptr, std::shared_ptr) или std::auto_ptr

A>std::auto_ptr устарел. в С++03 лучше использовать boost::scoped_ptr или boost::unique_ptr

Вот кстати пример того, почему лучше все-таки читать советы настоящих, а не доморощенных гуру.
Re[2]: TOP граблей С++ для новичков
От: Lorenzo_LAMAS  
Дата: 18.09.12 11:49
Оценка:
ой, я не заметил, что ты уже писал про такое. но, короче, когда человек пишет в стиле "назад в 1982 к С с классами" — это его ежедневный "паттерн" — неспособность освободить ресурсы.
Of course, the code must be complete enough to compile and link.
Re[3]: TOP граблей С++ для новичков
От: igna Россия  
Дата: 18.09.12 11:55
Оценка: +1
Здравствуйте, Lorenzo_LAMAS, Вы писали:

L_L>ой, я не заметил, что ты уже писал про такое. но, короче, когда человек пишет в стиле "назад в 1982 к С с классами" — это его ежедневный "паттерн" — неспособность освободить ресурсы.


А в С с классами не было деструктора?
Re[3]: Поймите и используйте STL
От: Piko  
Дата: 18.09.12 11:59
Оценка: 4 (1)
Здравствуйте, Abyx, Вы писали:

A>если С++03 — зачем функтор если достаточно функции


насколько я знаю фуктор подставляется в параметр шаблона как тип, то есть чистый compile-time, а функция как указатель на семейство функций со всеми вытекающими.
А как C++98 и C++03 отличаются в этом месте?
Re[4]: TOP граблей С++ для новичков
От: Lorenzo_LAMAS  
Дата: 18.09.12 12:06
Оценка:
I>А в С с классами не было деструктора?

странно, что ты не понял — я не об особенностях определенной реализации С++ говорю, а о том, что люди на С++ пишут, как будто у них С или что похуже.
Of course, the code must be complete enough to compile and link.
Re[2]: Поймите и используйте STL
От: Сыроежка  
Дата: 18.09.12 12:07
Оценка:
Здравствуйте, Шебеко Евгений, Вы писали:

ШЕ>Каждый второй кандидат на предложение отсортировать массив, предлагает сортировку пузырьком!!!

ШЕ>Только два кандидата, с помощью гугла, смогли дать более-менее рабочий код с использованием std::sort()

А я знаю сортировку выбором!

Если бы мне предложили отсортировать контейнер, то я специально использовал бы сортировку выбором с использованием станалртных алгоритмов!

ШЕ>Вот тестовое задание, которое вводит в ступор всех кандидатов:



ШЕ>
ШЕ>#include <string>
ШЕ>#include <vector>
ШЕ>#include <algorithm>

ШЕ>struct human_t
ШЕ>{
ШЕ>    std::string first_name;
ШЕ>    std::string last_name;
ШЕ>    unsigned age;
    
ШЕ>    human_t()
ШЕ>    {
ШЕ>        age=0;
ШЕ>    }
ШЕ>};


ШЕ>int main(int argc,char** argv)
ШЕ>{
ШЕ>    std::vector<human_t> v;

ШЕ>    return 0;
ШЕ>}

ШЕ>Отсортировать v по фамилии и имени.

ШЕ>


ШЕ>Решение довольно простое:


ШЕ>
ШЕ>#include <string>
ШЕ>#include <vector>
ШЕ>#include <algorithm>

ШЕ>struct human_t
ШЕ>{
ШЕ>    std::string first_name;
ШЕ>    std::string last_name;
ШЕ>    unsigned age;
    
ШЕ>    human_t()
ШЕ>    {
ШЕ>        age=0;
ШЕ>    }
ШЕ>};

ШЕ>//предикат
ШЕ>struct human_pr
ШЕ>{
ШЕ>    inline bool operator()(const human_t& a,const human_t& b) const
ШЕ>    {
ШЕ>        if(a.last_name!=b.last_name)return a.last_name<b.last_name;
ШЕ>        return a.first_name<b.first_name;
ШЕ>    }
ШЕ>};
ШЕ>

ШЕ>int main(int argc,char** argv)
ШЕ>{
ШЕ>    std::vector<human_t> v;

ШЕ>    std::sort(v.begin(),v.end(),human_pr());
ШЕ>
ШЕ>    return 0;
ШЕ>}

ШЕ>



Вообще-то у std::pair уже определен оператор <. Поэтому не надо изобретать велосипед, а использовать реализацию этого оператора.
Меня можно встретить на www.cpp.forum24.ru
Re[3]: Поймите и используйте STL
От: Сыроежка  
Дата: 18.09.12 12:15
Оценка:
Здравствуйте, Abyx, Вы писали:

A>Здравствуйте, Шебеко Евгений, Вы писали:


ШЕ>>std::hash_map<>,std::hash_set<>


A>нету таких классов в std


ШЕ>>//предикат

ШЕ>>struct human_pr
ШЕ>>{
ШЕ>> inline bool operator()(const human_t& a,const human_t& b) const
ШЕ>> {
ШЕ>> if(a.last_name!=b.last_name)return a.last_name<b.last_name;
ШЕ>> return a.first_name<b.first_name;
ШЕ>> }
ШЕ>>};
ШЕ>>


A>если С++03 — зачем функтор если достаточно функции

A>если С++ — должна быть лямбда.

К функции вы не сможете применить адаптеры, как, например, std::not1.

Лямбда выражения целесообразно применять, лишь когда они используется в какой-то локальной области кода. Если же они захватывают локальные переменные, а ич функциональность должна использоваться в нескольких местах кода и единиц трансляции, то лучше использовать функциональные объекты.
Меня можно встретить на www.cpp.forum24.ru
Re[4]: Поймите и используйте STL
От: Abyx Россия  
Дата: 18.09.12 12:17
Оценка:
Здравствуйте, Piko, Вы писали:

A>>если С++03 — зачем функтор если достаточно функции


P>насколько я знаю фуктор подставляется в параметр шаблона как тип, то есть чистый compile-time, а функция как указатель на семейство функций со всеми вытекающими.


да, в каких-то версиях MSVC именно так (хз как в MSVC11), а в g++ вроде функция инлайнится, IIRC
In Zen We Trust
Re[5]: TOP граблей С++ для новичков
От: igna Россия  
Дата: 18.09.12 12:25
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

L_L>странно, что ты не понял — я не об особенностях определенной реализации С++ говорю, а о том, что люди на С++ пишут, как будто у них С или что похуже.


Мне в самом деле стало интересно, с самого ли начала в C++ или C с классами был деструктор.

А вот по поводу "как будто у них С" несогласен. На C, когда в функции выделяются русурсы, return как правило один — в конце. (Или его вообще нет, если функция ничего не возвращает.)
Re[5]: Поймите и используйте STL
От: Piko  
Дата: 18.09.12 12:30
Оценка: +1
Здравствуйте, Abyx, Вы писали:

A>>>если С++03 — зачем функтор если достаточно функции

P>>насколько я знаю фуктор подставляется в параметр шаблона как тип, то есть чистый compile-time, а функция как указатель на семейство функций со всеми вытекающими.
A>да, в каких-то версиях MSVC именно так (хз как в MSVC11), а в g++ вроде функция инлайнится, IIRC

функция конечно может инлайнится — и она скорей всего нормально инлайнится во многих версиях msvc, и gcc, но у функтора намного больше шансов.
написать лишние двадцать буковок для функтора — не проблема, большой смысловой нагрузки они не несут, ошибится в них трудно
Re[4]: Поймите и используйте STL
От: Piko  
Дата: 18.09.12 12:39
Оценка:
Здравствуйте, Сыроежка, Вы писали:

A>>если С++03 — зачем функтор если достаточно функции

A>>если С++ — должна быть лямбда.
С>К функции вы не сможете применить адаптеры, как, например, std::not1.

1. есть std::ptr_fun.
2. к human_pr not1 не применишь, во-первых он бинарный, во-вторых он не определяет argument_type.
3. нафига not1 в данной конкретной задаче?

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


Я удивлён, но мысль у тебя верная, браво!
Вот только к обсуждаемому примеру не относится, там лямбду использовать целесообразно
Re[2]: Копирующий конструктор и копирующий operator= по умолчанию.
От: PM  
Дата: 18.09.12 12:39
Оценка: +4 :)
Здравствуйте, Шебеко Евгений, Вы писали:

ШЕ>Если класс не содержит явного копирующего конструктора или operator=, то они создаются неявно.

ШЕ>Об этом надо помнить.

ШЕ>Допустим у нас есть класс, который содержит в себе указатель на свой буффер.


[тут был код очередного класса буфера]

Для меня new вне конструктора умного указателя (std::shared_ptr, std::unique_ptr или их аналогов из Boost) — признак плохого кода.

В прикладном коде new/delete не нужен, для буфера есть std::vector<char> или его суженный аналог:

class buffer
{
public:
   buffer() {}
   buffer(char const* data, size_t size) : data_(data, data + size) {}

   bool empty() const { return data_.empty(); }

   size_t size() const { return data_.size(); }
   void resize(size_t new_size) { data_.resize(new_size); }

   char const* data() const { return data_.empty()? nullptr : &data_[0]; }
   char* data() { return data_.empty()? nullptr : &data_[0]; }
private:
   std::vector<char> data_;
};
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.