Модерний C++ робить програмування чистішим, безпечнішим і ефективнішим. Цей блог проведе вас через лямбда-функції та локальні змінні, захоплення за допомогою переміщення, генерацію випадкових чисел і магію std::unique_ptr
. Готові підняти свої навички C++ на новий рівень? Починаємо! 💡
🔐 Лямбда-локальні змінні
У сучасному C++ лямбда-функції — це не просто легковажні анонімні функції; вони також дозволяють визначати локальні змінні всередині свого тіла.
Основні факти про лямбда-локальні змінні:
- Оголошення: Змінні в тілі лямбди не обов'язково повинні оголошуватись через
auto
, але можуть бути. - Ініціалізація: Змінні повинні бути явно ініціалізовані перед використанням.
Приклад: Локальні змінні в лямбді
#include
int main() {
auto myLambda = []() {
int localVar = 42; // Лямбда-локальна змінна
std::cout << "Лямбда-локальна змінна: " << localVar << "\n";
};
myLambda();
return 0;
}
🧩 Основний висновок: Лямбда-локальні змінні обмежені до тіла лямбди, що забезпечує безпечне і ізольоване використання.
🧳 Ініціалізація лямбда-локальних змінних із захоплених змінних
Лямбда-функції можуть ініціалізувати свої локальні змінні за допомогою захоплених змінних.
Як захоплювати змінні:
- Використовуйте
[x]
для захоплення за значенням. - Використовуйте
[&x]
для захоплення за посиланням.
Приклад: Захоплення і ініціалізація локальної змінної
#include
int main() {
int base = 10;
auto myLambda = [base]() {
int localVar = base + 5; // Ініціалізація localVar за допомогою захопленої змінної
std::cout << "Base: " << base << ", Лямбда-локальна змінна: " << localVar << "\n";
};
myLambda();
return 0;
}
📦 Захоплення за допомогою переміщення в лямбдах
Іноді ви хочете перемістити ресурси в лямбду, щоб уникнути копіювання. Використовуйте функцію std::move
і захоплюйте змінну за значенням.
Приклад: Захоплення за допомогою переміщення
#include
#include
#include
int main() {
std::string largeString = "This is a large string";
auto myLambda = [str = std::move(largeString)]() {
std::cout << "Захоплений рядок: " << str << "\n";
};
myLambda();
// largeString тепер порожній
std::cout << "Оригінальний рядок після переміщення: " << largeString << "\n";
return 0;
}
🧩 Основний висновок: Захоплення за допомогою переміщення забезпечує ефективне передавання прав власності в лямбди, особливо для великих або не-копійованих об'єктів.
🎲 Генерація випадкових чисел
Модерний C++ надає бібліотеку `` для надійної генерації випадкових чисел.
Приклад: Випадкові цілі числа (від 0 до 100)
#include
#include
int main() {
std::random_device rd; // Джерело насіння
std::mt19937 gen(rd()); // Генератор Mersenne Twister
std::uniform_int_distribution<> distrib(0, 100);
for (int i = 0; i < 10; ++i) {
std::cout << distrib(gen) << " ";
}
return 0;
}
Приклад: Випадкові числа з плаваючою комою (від 0 до 1)
#include
#include
int main() {
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_real_distribution<> distrib(0.0, 1.0);
for (int i = 0; i < 10; ++i) {
std::cout << distrib(gen) << " ";
}
return 0;
}
❌ Чому слід уникати локальних випадкових генераторів?
Використання випадкового генератора як локальної змінної ініціалізує його щоразу, що може призвести до передбачуваних або не оптимальних випадкових значень. Замість цього використовуйте глобальний або статичний генератор випадкових чисел для збереження стану між викликами.
🧠 Розуміння std::unique_ptr
Що таке std::unique_ptr
?
- Це смарт-вказівник, що володіє динамічно виділеним об'єктом.
- Забезпечує звільнення ресурсу, коли
unique_ptr
виходить із області видимості. - Запобігає копіюванню (володіння не може бути спільним).
Ефективність проти сирих вказівників:
- Використання пам'яті: Немає додаткових витрат (лише вказівник).
- Ефективність: Автоматичне управління ресурсами, що запобігає витокам пам'яті.
RAII і std::unique_ptr
:
RAII (Resource Acquisition Is Initialization) забезпечує автоматичне очищення ресурсів (наприклад, пам'яті).
std::unique_ptr
є прикладом RAII, оскільки:
- Перехоплює володіння під час ініціалізації.
- Звільняє володіння при знищенні.
🛠️ Використання std::unique_ptr
Приклад: Базове використання
#include
#include
int main() {
std::unique_ptr ptr = std::make_unique(42); // Ініціалізація
std::cout << "Значення: " << *ptr << "\n";
// Переміщення володіння
std::unique_ptr newPtr = std::move(ptr);
std::cout << "Нове значення: " << *newPtr << "\n";
return 0;
}
Сумісність з C++11:
- Замість
std::make_unique
використовуйтеstd::unique_ptr(new int(42))
.
🚀 Заключні думки
Модерні можливості C++, такі як лямбда-функції, генерація випадкових чисел і std::unique_ptr
, роблять ваш код чистішим, безпечнішим і ефективнішим. Розуміючи та опановуючи ці інструменти, ви зможете писати високоякісні, підтримувані програми з легкістю.
by : Malinda Gamage
Перекладено з: 🚀 Modern C++: Diving Deeper into Lambdas, Random Numbers, and Smart Pointers 🧠