Прагнеш швидкості? Передавай за значенням.

Тільки чесно: які почуття викликає в вас наступний код?

std::vector<std::string> get_names();
...
std::vector<std::string> const names = get_names();

Відверто, я б занервував. В принципі, по завершені get_names() ми маємо копіювати вектор рядків. Потім ми маємо копіювати його знов, коли ініціалізуємо names, і маємо знищити першу копію. Якщо в векторі N рядків, кожне копіювання може вимагати аж по N+1 виділень пам’яті і безліч недружнього щодо кешу доступу до даних, коли вміст рядка копіюється.

Радше ніж відчувати цю тривогу, я часто повертався до використання передачі за посиланням, щоб уникнути непотрібних копій:

get_names(std::vector<std::string>& out_param );
...
std::vector<std::string> names;
get_names( names );

На жаль, цей підхід далекий від досконалості.

  • Об’єм коду виріс на 150%
  • Нам довелось поступитись сталістю, бо ми змінюємо names.
  • Як функційні програмісти захочуть нам нагадати, зміна параметра ускладнює розуміння через підривання прозорості посилань і міркувань щодо рівнянь (equational reasoning.).
  • Ми більше не дотримуємось суворої семантики передачі за значенням для names.

Але, чи дійсно конче необхідно так плутати наш код для досягнення дієвості? На щастя, виявляється, що відповідь ні (особливо, якщо ви використовуєте C++0x). Ця стаття перша в серії, що досліджує п-значення (rvalues) та їх вплив на дієвість семантики значень (value semantics) в C++.

Read more…

Переведення числового запису в його рядковий відповідник

У багатьох програмістів в житті наступає момент, коли виникає потреба в переведенні числа, наприклад прочитаного з бази даних, в рядок як воно читається. Зазвичай для формування фінансових документів. Таке завдання випало й мені. Результат програми виглядає так:
123.12 – сто двадцять три грн. 12 коп.
123832 – сто двадцять три тисячі вiсiмсот тридцять двi грн. 12 коп.
12394355.12 – дванадцять мiльйонiв триста дев’яносто чотири тисячі триста п’ятдесят п’ять грн. 12 коп.

Далі подаю код:
Read more…

Categories: Uncategorized

Rvalue посилання: C++0x можливості в VC10

Листопад 29, 2011 Залишити коментар
л- та п-значення в C++98/03

Для розуміння правосторонніх посилань (rvalue reference) в C++0x, ви маєте розуміти лівосторонні й правосторонні значення в C++98/03.

Терміни ‘л-значення’ та ‘п-значення’ викликають плутанину, це пов’язано з їхньою історією. Ці поняття прийшли з С і тоді стали частиною C++. Для збереження часу, ми проминемо їхню історію, включно з причинами чому вони називаються ‘л-значення’ та ‘п-значення’ й одразу розглянемо як вони працюють в C++98/03. (Добре, це не велика таємниця, що ‘Л’ означає ‘лівий’, а ‘R’ – ‘правий’. Але самі поняття розвинулись і змінились, і тепер їхні назви не дуже точні. Замість прослуховування уроку з історії їх появи, ви можете уявити, що вони мають довільні назви, приміром, ‘верхня частка’ та ‘нижня частка’, і при цьому ви нічого не втратите.)

C++03 3.10/1 каже: ‘Кожен вираз є або л-значенням або п-значенням.’ Важливо пам’ятати, що л- або п-значеннєвість це властивість виразу, а не об’єкта.
Read more…

Categories: Uncategorized

Лямбда-вирази, auto та static_assert: C++0x можливості в VC10

Лямбда-вирази

В C++0x, “лямбда-вирази” непрямим чином створюють функцональні об’єкти, які потім поводяться як функціональні об’єкти написані вручну. Наведемо “Hello, World” лямбда-вираз:

#include <algorithm>
#include <iostream>
#include <ostream>
#include <vector>

using namespace std;

int main() {
    vector<int> v;

    for (int i = 0; i < 10; ++i)
        v.push_back(i);

    for_each(v.begin(), v.end(), [](int n) { cout << n << " "; });
    cout << endl;
}

0 1 2 3 4 5 6 7 8 9
Read more…

Як розробити простий UDP сервер і клієнт із використанням WinSock.

Вступ

Цей проект містить прості програми-приклади UDP сервера та клієнта. Якщо ви ніколи не писали програми, що використовують UDP, це прекрасний проект для початку. Сервер виконується на локальному комп’ютері та очікує дейтаграму із запитом поточного серверного часу з віддаленого комп’ютера. По отриманню такої дейтаграми сервер повертає свій поточний час клієнту, який відображає його.

Підвалини

UDP позначає протокол дейтаграм користувача. Клієнт відсилає дейтаграму серверу, який у свою чергу обробляє дані відсилає відповідь в зворотньому напрямку. В цій статті показується як використовувати функції sendto та recvfrom.
Read more…

Вступ у використання рекурсії в C++

Липень 25, 2011 3 коментарів
1. Вступ

Загалом, рекурсія значить самоповторюваний шаблон. В математиці це може бути функція визначена через себе. Інакше кажучи, це функція, що викликає сама себе. Кожна рекурсивна функція має умову завершення; інакше вона буде викликати себе безперестанку, і ця умова може бути названою базова умова.

Зазвичай, рекурсія це трошки складна для розуміння більшості студентів концепція.

2. Типи рекурсії

В C++, типи рекурсії можна визначити більш ніж за одним виміром. З одного боку, їх можна категоризувати як рекурсії часц виконання і як рекурсії часу компіляції через використання шаблонів.
Read more…

Як облаштувати сирцевий код шаблона

Введення

Часто мене запитували складно чи лекго програмувати з шаблонами. Відповідь яку я зазвичай давав така: “Це легко коли ти використовуєш, але складно коли створюєш їх”. Лиш погляньте на деякі бібліотеки шаблонів, які використовуються повсякденно, наприклад, STL, ATL, WTL, деякі бібліотеки з Boost, і ви побачите, що я маю на увазі під цим. Ці бібліотеки є чудовим прикладом принципу “простий інтерфейс – складна реалізація”.
Read more…

Follow

Get every new post delivered to your Inbox.