23
EE3490: Kỹ thuật lập trình HK1 2018/2019 TS. Đào Trung Kiên – ĐH Bách khoa Hà Nội Bài 13: C++11 1

Bài 13: C++11 - mica.edu.vn. C++ - C++11.pdfBài 13: C++11 1. EE3490: Kỹthuậtlậptrình –HK1 2018/2019 TS. ĐàoTrung Kiên –ĐH Bách khoa Hà Nội Các phiên bảnC++

  • Upload
    others

  • View
    0

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Bài 13: C++11 - mica.edu.vn. C++ - C++11.pdfBài 13: C++11 1. EE3490: Kỹthuậtlậptrình –HK1 2018/2019 TS. ĐàoTrung Kiên –ĐH Bách khoa Hà Nội Các phiên bảnC++

EE3490: Kỹ thuật lập trình – HK1 2018/2019

TS. Đào Trung Kiên – ĐH Bách khoa Hà Nội

Bài 13: C++11

1

Page 2: Bài 13: C++11 - mica.edu.vn. C++ - C++11.pdfBài 13: C++11 1. EE3490: Kỹthuậtlậptrình –HK1 2018/2019 TS. ĐàoTrung Kiên –ĐH Bách khoa Hà Nội Các phiên bảnC++

EE3490: Kỹ thuật lập trình – HK1 2018/2019

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

Page 3: Bài 13: C++11 - mica.edu.vn. C++ - C++11.pdfBài 13: C++11 1. EE3490: Kỹthuậtlậptrình –HK1 2018/2019 TS. ĐàoTrung Kiên –ĐH Bách khoa Hà Nội Các phiên bảnC++

EE3490: Kỹ thuật lập trình – HK1 2018/2019

TS. Đào Trung Kiên – ĐH Bách khoa Hà Nội

Tự suy đoán kiểu

Ví dụ:

map<string, pair<string, int>> m;

// map<string, pair<string, int>>::iterator itr = m.begin();

auto itr = m.begin();

// pair<string, int>& a = m["KTLT"];

auto& a = m["KTLT"];

// pair<string, int> b;

decltype(a) b;

3

Page 4: Bài 13: C++11 - mica.edu.vn. C++ - C++11.pdfBài 13: C++11 1. EE3490: Kỹthuậtlậptrình –HK1 2018/2019 TS. ĐàoTrung Kiên –ĐH Bách khoa Hà Nội Các phiên bảnC++

EE3490: Kỹ thuật lập trình – HK1 2018/2019

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<string> l;

vector<complex> v;

for (int x : a) {

//...

}

for (string& x : l) {

//...

}

for (complex& x : v) {

//...

}

4

Page 5: Bài 13: C++11 - mica.edu.vn. C++ - C++11.pdfBài 13: C++11 1. EE3490: Kỹthuậtlậptrình –HK1 2018/2019 TS. ĐàoTrung Kiên –ĐH Bách khoa Hà Nội Các phiên bảnC++

EE3490: Kỹ thuật lập trình – HK1 2018/2019

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<int> p1(new int(10));

shared_ptr<int> p2 = p1;

*p2 = 20;

// bộ nhớ sẽ được thu hồi khi

// tham chiếu cuối cùng được huỷ

5

Page 6: Bài 13: C++11 - mica.edu.vn. C++ - C++11.pdfBài 13: C++11 1. EE3490: Kỹthuậtlậptrình –HK1 2018/2019 TS. ĐàoTrung Kiên –ĐH Bách khoa Hà Nội Các phiên bảnC++

EE3490: Kỹ thuật lập trình – HK1 2018/2019

TS. Đào Trung Kiên – ĐH Bách khoa Hà Nội

Đa luồng (multithreading)

& Lập trình song song (concurrency)

6

Page 7: Bài 13: C++11 - mica.edu.vn. C++ - C++11.pdfBài 13: C++11 1. EE3490: Kỹthuậtlậptrình –HK1 2018/2019 TS. ĐàoTrung Kiên –ĐH Bách khoa Hà Nội Các phiên bảnC++

EE3490: Kỹ thuật lập trình – HK1 2018/2019

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 <thread>

Lớp std::thread

Mỗi luồng được thực thi trong một hàm gọi là thread function

7

Page 8: Bài 13: C++11 - mica.edu.vn. C++ - C++11.pdfBài 13: C++11 1. EE3490: Kỹthuậtlậptrình –HK1 2018/2019 TS. ĐàoTrung Kiên –ĐH Bách khoa Hà Nội Các phiên bảnC++

EE3490: Kỹ thuật lập trình – HK1 2018/2019

TS. Đào Trung Kiên – ĐH Bách khoa Hà Nội

Ví dụ

#include <iostream>

#include <chrono>

#include <thread>

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

Page 9: Bài 13: C++11 - mica.edu.vn. C++ - C++11.pdfBài 13: C++11 1. EE3490: Kỹthuậtlậptrình –HK1 2018/2019 TS. ĐàoTrung Kiên –ĐH Bách khoa Hà Nội Các phiên bảnC++

EE3490: Kỹ thuật lập trình – HK1 2018/2019

TS. Đào Trung Kiên – ĐH Bách khoa Hà Nội

Luồng với tham số

#include <iostream>

#include <chrono>

#include <thread>

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

Page 10: Bài 13: C++11 - mica.edu.vn. C++ - C++11.pdfBài 13: C++11 1. EE3490: Kỹthuậtlậptrình –HK1 2018/2019 TS. ĐàoTrung Kiên –ĐH Bách khoa Hà Nội Các phiên bảnC++

EE3490: Kỹ thuật lập trình – HK1 2018/2019

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

Page 11: Bài 13: C++11 - mica.edu.vn. C++ - C++11.pdfBài 13: C++11 1. EE3490: Kỹthuậtlậptrình –HK1 2018/2019 TS. ĐàoTrung Kiên –ĐH Bách khoa Hà Nội Các phiên bảnC++

EE3490: Kỹ thuật lập trình – HK1 2018/2019

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>

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

Page 12: Bài 13: C++11 - mica.edu.vn. C++ - C++11.pdfBài 13: C++11 1. EE3490: Kỹthuậtlậptrình –HK1 2018/2019 TS. ĐàoTrung Kiên –ĐH Bách khoa Hà Nội Các phiên bảnC++

EE3490: Kỹ thuật lập trình – HK1 2018/2019

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 <iostream>

#include <thread>

#include <chrono>

#include <mutex>

#include <ppl.h>

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;

}

Page 13: Bài 13: C++11 - mica.edu.vn. C++ - C++11.pdfBài 13: C++11 1. EE3490: Kỹthuậtlậptrình –HK1 2018/2019 TS. ĐàoTrung Kiên –ĐH Bách khoa Hà Nội Các phiên bảnC++

EE3490: Kỹ thuật lập trình – HK1 2018/2019

TS. Đào Trung Kiên – ĐH Bách khoa Hà Nội

Hàm lambda

13

Page 14: Bài 13: C++11 - mica.edu.vn. C++ - C++11.pdfBài 13: C++11 1. EE3490: Kỹthuậtlậptrình –HK1 2018/2019 TS. ĐàoTrung Kiên –ĐH Bách khoa Hà Nội Các phiên bảnC++

EE3490: Kỹ thuật lập trình – HK1 2018/2019

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

Page 15: Bài 13: C++11 - mica.edu.vn. C++ - C++11.pdfBài 13: C++11 1. EE3490: Kỹthuậtlậptrình –HK1 2018/2019 TS. ĐàoTrung Kiên –ĐH Bách khoa Hà Nội Các phiên bảnC++

EE3490: Kỹ thuật lập trình – HK1 2018/2019

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

Page 16: Bài 13: C++11 - mica.edu.vn. C++ - C++11.pdfBài 13: C++11 1. EE3490: Kỹthuậtlậptrình –HK1 2018/2019 TS. ĐàoTrung Kiên –ĐH Bách khoa Hà Nội Các phiên bảnC++

EE3490: Kỹ thuật lập trình – HK1 2018/2019

TS. Đào Trung Kiên – ĐH Bách khoa Hà Nội

Ví dụ 2

int func(int a, function<int (int)> 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

Page 17: Bài 13: C++11 - mica.edu.vn. C++ - C++11.pdfBài 13: C++11 1. EE3490: Kỹthuậtlậptrình –HK1 2018/2019 TS. ĐàoTrung Kiên –ĐH Bách khoa Hà Nội Các phiên bảnC++

EE3490: Kỹ thuật lập trình – HK1 2018/2019

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

Page 18: Bài 13: C++11 - mica.edu.vn. C++ - C++11.pdfBài 13: C++11 1. EE3490: Kỹthuậtlậptrình –HK1 2018/2019 TS. ĐàoTrung Kiên –ĐH Bách khoa Hà Nội Các phiên bảnC++

EE3490: Kỹ thuật lập trình – HK1 2018/2019

TS. Đào Trung Kiên – ĐH Bách khoa Hà Nội

Tham chiếu rvalue

& Ý nghĩa move

18

Page 19: Bài 13: C++11 - mica.edu.vn. C++ - C++11.pdfBài 13: C++11 1. EE3490: Kỹthuậtlậptrình –HK1 2018/2019 TS. ĐàoTrung Kiên –ĐH Bách khoa Hà Nội Các phiên bảnC++

EE3490: Kỹ thuật lập trình – HK1 2018/2019

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

Page 20: Bài 13: C++11 - mica.edu.vn. C++ - C++11.pdfBài 13: C++11 1. EE3490: Kỹthuậtlậptrình –HK1 2018/2019 TS. ĐàoTrung Kiên –ĐH Bách khoa Hà Nội Các phiên bảnC++

EE3490: Kỹ thuật lập trình – HK1 2018/2019

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

Page 21: Bài 13: C++11 - mica.edu.vn. C++ - C++11.pdfBài 13: C++11 1. EE3490: Kỹthuậtlậptrình –HK1 2018/2019 TS. ĐàoTrung Kiên –ĐH Bách khoa Hà Nội Các phiên bảnC++

EE3490: Kỹ thuật lập trình – HK1 2018/2019

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

Page 22: Bài 13: C++11 - mica.edu.vn. C++ - C++11.pdfBài 13: C++11 1. EE3490: Kỹthuậtlậptrình –HK1 2018/2019 TS. ĐàoTrung Kiên –ĐH Bách khoa Hà Nội Các phiên bảnC++

EE3490: Kỹ thuật lập trình – HK1 2018/2019

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

Page 23: Bài 13: C++11 - mica.edu.vn. C++ - C++11.pdfBài 13: C++11 1. EE3490: Kỹthuậtlậptrình –HK1 2018/2019 TS. ĐàoTrung Kiên –ĐH Bách khoa Hà Nội Các phiên bảnC++

EE3490: Kỹ thuật lập trình – HK1 2018/2019

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