Các phiên bản C++
C++98 (đã học trong các bài trước):
Được ISO chuẩn hoá lần đầu tiên
C++03:
Một số thay đổi nhỏ
C++0x / C++11:
Rất nhiều cập nhật mới
Nhiều tính năng được lấy lại từ thư viện boost
C++14:
Một số mở rộng so với C++11
C++17:
Đang thảo luận
23 trang |
Chia sẻ: phuongt97 | Lượt xem: 381 | Lượt tải: 0
Bạn đang xem trước 20 trang nội dung tài liệu Bài giảng Kỹ thuật lập trình - Bài 13: C++11 - Đào Trung Kiên, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
EE3490: Kỹ thuật lập trình – HK1 2017/2018
TS. Đào Trung Kiên – ĐH Bách khoa Hà Nội
Bài 13: C++11
1
EE3490: Kỹ thuật lập trình – HK1 2017/2018
TS. Đào Trung Kiên – ĐH Bách khoa Hà Nội
Các phiên bản C++
C++98 (đã học trong các bài trước):
Được ISO chuẩn hoá lần đầu tiên
C++03:
Một số thay đổi nhỏ
C++0x / C++11:
Rất nhiều cập nhật mới
Nhiều tính năng được lấy lại từ thư viện boost
C++14:
Một số mở rộng so với C++11
C++17:
Đang thảo luận
2
EE3490: Kỹ thuật lập trình – HK1 2017/2018
TS. Đào Trung Kiên – ĐH Bách khoa Hà Nội
Tự suy đoán kiểu
Ví dụ:
map> m;
// map>::iterator itr = m.begin();
auto itr = m.begin();
// pair& a = m["KTLT"];
auto& a = m["KTLT"];
// pair b;
decltype(a) b;
3
EE3490: Kỹ thuật lập trình – HK1 2017/2018
TS. Đào Trung Kiên – ĐH Bách khoa Hà Nội
Vòng lặp for theo khoảng (range-based for loop)
double a[10];
list l;
vector v;
for (int x : a) {
//...
}
for (string& x : l) {
//...
}
for (complex& x : v) {
//...
}
4
EE3490: Kỹ thuật lập trình – HK1 2017/2018
TS. Đào Trung Kiên – ĐH Bách khoa Hà Nội
Con trỏ thông minh (smart pointers)
Là kiểu trừu tượng cho phép mô phỏng các con trỏ,
nhưng bổ sung thêm một số tính năng khác:
Quản lý bộ nhớ tự động
Kiểm tra phạm vi
Ví dụ:
shared_ptr p1(new int(10));
shared_ptr p2 = p1;
*p2 = 20;
// bộ nhớ sẽ được thu hồi khi
// tham chiếu cuối cùng được huỷ
5
EE3490: Kỹ thuật lập trình – HK1 2017/2018
TS. Đào Trung Kiên – ĐH Bách khoa Hà Nội
Đa luồng (multithreading)
& Lập trình song song (concurrency)
6
EE3490: Kỹ thuật lập trình – HK1 2017/2018
TS. Đào Trung Kiên – ĐH Bách khoa Hà Nội
Luồng (threads)
Cho phép thực thi các nhiệm vụ đồng thời (song song, không đồng
bộ), chú ý phân biệt luồng và tiến trình (process)
Luôn có ít nhất một luồng trong chương trình, được tạo cho hàm
main: được gọi là luồng chính
Trước C++11, các luồng được quản lý bởi các thư viện ngoài:
POSIX thread (pthread)
Windows API
OpenMP
MPI
Từ C++11, đa luồng là một tính năng có sẵn
#include
Lớp std::thread
Mỗi luồng được thực thi trong một hàm gọi là thread function
7
EE3490: Kỹ thuật lập trình – HK1 2017/2018
TS. Đào Trung Kiên – ĐH Bách khoa Hà Nội
Ví dụ
#include
#include
#include
using namespace std;
void task1() {
for (int i = 0; i < 100;
i++) {
this_thread::sleep_for(
chrono::milliseconds(100));
cout << "Thread 1\n";
}
}
void task2() {
for (int i = 0; i < 100;
i++) {
this_thread::sleep_for(
chrono::milliseconds(100));
cout << "Thread 2\n";
}
}
void main() {
thread t(task1);
task2();
t.join();
}
8
EE3490: Kỹ thuật lập trình – HK1 2017/2018
TS. Đào Trung Kiên – ĐH Bách khoa Hà Nội
Luồng với tham số
#include
#include
#include
using namespace std;
void task(int* n) {
int i, t;
for (i=0; i<100; i++) {
t = *n;
this_thread::sleep_for(
chrono::milliseconds(1));
*n = t + 1;
}
}
void main() {
thread a[10];
int i, n = 0;
for (i=0; i<10; i++)
a[i] = thread(
task, &n);
for (i=0; i<10; i++)
a[i].join();
cout << n << endl;
}
9
EE3490: Kỹ thuật lập trình – HK1 2017/2018
TS. Đào Trung Kiên – ĐH Bách khoa Hà Nội
Critical sections & quản lý sử dụng tài nguyên
Các luồng trong cùng một process chia sẻ bộ nhớ
Một luồng có thể sử dụng bộ nhớ được cấp phát từ các
luồng khác
Việc cập nhật các biến chung từ các luồng khác
nhau có thể dẫn đến kết quả không mong muốn
10
Luồng 2
t = i;
t ++;
i = t;
Luồng 1
t = i;
t ++;
i = t;
Giá trị
i = 10
t#1 = 10
t#2 = 10
t#1 = 11
t#2 = 11
i = 11
i = 11
Việc sử dụng tài
nguyên phải được
quản lý
Critical sections
Các tài nguyên có
thể được hiểu theo
nghĩa rộng
EE3490: Kỹ thuật lập trình – HK1 2017/2018
TS. Đào Trung Kiên – ĐH Bách khoa Hà Nội
Lớp mutex
Mutex = mutual exclusion (loại trừ lẫn nhau)
không quá 1 luồng thực thi đoạn mã ở một thời điểm
11
#include
mutex m;
void task(int* n) {
int i, t;
for (i=0; i<100; i++) {
m.lock();
t = *n;
this_thread::sleep_for(chrono::milliseconds(1));
*n = t + 1;
m.unlock();
}
}
critical
section
EE3490: Kỹ thuật lập trình – HK1 2017/2018
TS. Đào Trung Kiên – ĐH Bách khoa Hà Nội
Lớp parallel_for
Duyệt các phần tử và thực thi một hàm cho trước
một cách song song (tối ưu theo số CPU của máy)
12
#include
#include
#include
#include
#include
using namespace std;
using namespace
concurrency;
int n = 0;
mutex m;
void task(int itr) {
for (int i=0; i<100; i++) {
m.lock();
int t = n;
this_thread::sleep_for(
chrono::milliseconds(1));
n = t + 1;
m.unlock();
}
}
void main() {
parallel_for(0, 10, task);
cout << n << endl;
}
EE3490: Kỹ thuật lập trình – HK1 2017/2018
TS. Đào Trung Kiên – ĐH Bách khoa Hà Nội
Hàm lambda
13
EE3490: Kỹ thuật lập trình – HK1 2017/2018
TS. Đào Trung Kiên – ĐH Bách khoa Hà Nội
Khái niệm
Còn gọi là hàm không tên, được định nghĩa trong các câu lệnh
Thường được dùng như tham số khi gọi các hàm khác
Có thể được chuyển kiểu thành hàm thông thường khi không có “capture”
nào
Cú pháp:
[các-capture](các-tham-số) -> kiểu-trả-về {
thực-thi
}
các-capture: danh sách các biến thuộc phạm vi định nghĩa được
sử dụng trong hàm, phân cách bằng dấu “,”. Ví dụ:
[a, &b, c, &d]: a và c bằng giá trị, b và d bằng tham chiếu
[&, a, b]: a và b bằng giá trị, còn lại bằng tham chiếu
[=, &a, &b]: a và b bằng tham chiếu, còn lại bằng giá trị
kiểu-trả-về: có thể bỏ qua nếu suy luận được
14
EE3490: Kỹ thuật lập trình – HK1 2017/2018
TS. Đào Trung Kiên – ĐH Bách khoa Hà Nội
Ví dụ 1
const int n = 10;
int x[n] = {...};
std::sort(x, x + n,
[](int a, int b) {
return abs(a) < abs(b);
}
);
Viết theo C++98:
bool compare(int a, int b) {
return abs(a) < abs(b);
}
std::sort(x, x + n, compare);
15
EE3490: Kỹ thuật lập trình – HK1 2017/2018
TS. Đào Trung Kiên – ĐH Bách khoa Hà Nội
Ví dụ 2
int func(int a, function lambda) {
return lambda(a);
}
void main() {
int n = 10, m = 20;
int p = func(n, [m](int i) {
return i*m;
});
cout << p << endl;
}
16
EE3490: Kỹ thuật lập trình – HK1 2017/2018
TS. Đào Trung Kiên – ĐH Bách khoa Hà Nội
parallel_for
void main() {
int n = 0;
mutex m;
parallel_for(0, 10, [&m, &n](int itr) {
for (int i = 0; i < 100; i++) {
m.lock();
int t = n;
this_thread::sleep_for(chrono::milliseconds(1));
n = t + 1;
m.unlock();
}
});
cout << n << endl;
}
17
EE3490: Kỹ thuật lập trình – HK1 2017/2018
TS. Đào Trung Kiên – ĐH Bách khoa Hà Nội
Tham chiếu rvalue
& Ý nghĩa move
18
EE3490: Kỹ thuật lập trình – HK1 2017/2018
TS. Đào Trung Kiên – ĐH Bách khoa Hà Nội
Lvalue và rvalue
Mỗi biểu thức C++ là một lvalue hoặc rvalue
Lvalues: các giá trị có thể tham chiếu (những gì có thể
lưu giá trị, có thể được đặt ở vế trái của câu lệnh gán)
Rvalues: các giá trị tạm thời không tồn tại sau khi biểu
thức dùng nó kết thúc (chỉ được đặt ở vế phải của câu
lệnh gán)
Ví dụ:
int i = 100;
const int a = x * y;
int& m = i;
19
EE3490: Kỹ thuật lập trình – HK1 2017/2018
TS. Đào Trung Kiên – ĐH Bách khoa Hà Nội
Ý nghĩa move
Xem constructor sao chép của lớp string:
string& operator =(const string& str) {
//
}
Ví dụ sử dụng:
s = "abc";
1. Giải phóng các tài nguyên s sử dụng
2. Sao chép tài nguyên từ đối tượng tạm thời
3. Giải phóng đối tượng tạm, và do đó, giải phóng các tài
nguyên nó sử dụng
Không tối ưu về hiệu năng hoạt động! Tại sao không
chuyển đổi (move) tài nguyên của các đối tượng cho nhau?
20
EE3490: Kỹ thuật lập trình – HK1 2017/2018
TS. Đào Trung Kiên – ĐH Bách khoa Hà Nội
Tham chiếu rvalue
Tham chiếu rvalue (string&&) là các tham chiếu tới
rvalue, được dùng trong quá trình move
s = "abc";
s = s1 + s2;
string ss(s1 + s2);
“Tham chiếu truyền thống” (string&) nay được gọi là
tham chiếu lvalue, được sử dụng trong quá trình copy
s = s1;
string ss(s1);
Ta cần phải định nghĩa thêm:
1 toán tử gán move (bên cạnh toán tử gán copy)
1 constructor move (bên cạnh constructor copy)
21
EE3490: Kỹ thuật lập trình – HK1 2017/2018
TS. Đào Trung Kiên – ĐH Bách khoa Hà Nội
Các constructor copy và move
class string {
protected:
char* p;
public:
string(const string& s) {
//... (as before)
}
string(const string&& s) {
p = s.p;
}
};
22
EE3490: Kỹ thuật lập trình – HK1 2017/2018
TS. Đào Trung Kiên – ĐH Bách khoa Hà Nội
Các toán tử gán copy và move
class string {
protected:
char* p;
public:
string& operator =(const string& s) {
//... (as before)
}
string& operator =(const string&& s) {
p = s.p;
return *this;
}
};
23
Các file đính kèm theo tài liệu này:
- bai_giang_ky_thuat_lap_trinh_bai_13_c11_dao_trung_kien.pdf