Merge ; commit '63746a2f835f9521273ae82a594393cc8ad9baff'
Conflicts: .obsidian/workspace
This commit is contained in:
6
.obsidian/daily-notes.json
vendored
6
.obsidian/daily-notes.json
vendored
@@ -1 +1,5 @@
|
|||||||
{"folder":"Daily","format":"YYYY-MM-DD(ddd)","template":"PARA/003 - Resources(資源)/99. templates/日記"}
|
{
|
||||||
|
"folder": "01. Daily",
|
||||||
|
"format": "YYYY-MM-DD(ddd)",
|
||||||
|
"template": "02. PARA/03. Resources(資源)/99. templates/日記"
|
||||||
|
}
|
||||||
71
.obsidian/workspace
vendored
71
.obsidian/workspace
vendored
@@ -11,7 +11,7 @@
|
|||||||
"type": "markdown",
|
"type": "markdown",
|
||||||
"state": {
|
"state": {
|
||||||
"file": "00. TOP/01. TODO.md",
|
"file": "00. TOP/01. TODO.md",
|
||||||
"mode": "source",
|
"mode": "preview",
|
||||||
"source": true
|
"source": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -35,7 +35,11 @@
|
|||||||
"type": "mobile-drawer",
|
"type": "mobile-drawer",
|
||||||
"children": [
|
"children": [
|
||||||
{
|
{
|
||||||
"id": "88e1cff7a30f6953",
|
"id": "dbd6f1d450f54a18",
|
||||||
|
"type": "tabs",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "f0c230180a9faaa1",
|
||||||
"type": "leaf",
|
"type": "leaf",
|
||||||
"state": {
|
"state": {
|
||||||
"type": "file-explorer",
|
"type": "file-explorer",
|
||||||
@@ -43,12 +47,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "ceb171daf1327c40",
|
"id": "81a47da514b9d823",
|
||||||
"type": "leaf",
|
"type": "leaf",
|
||||||
"state": {
|
"state": {
|
||||||
"type": "search",
|
"type": "search",
|
||||||
"state": {
|
"state": {
|
||||||
"query": "",
|
"query": "shared_ptr",
|
||||||
"matchingCase": false,
|
"matchingCase": false,
|
||||||
"explainSearch": false,
|
"explainSearch": false,
|
||||||
"collapseAll": false,
|
"collapseAll": false,
|
||||||
@@ -56,6 +60,8 @@
|
|||||||
"sortOrder": "alphabetical"
|
"sortOrder": "alphabetical"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "dc8bb41204529396",
|
"id": "dc8bb41204529396",
|
||||||
@@ -76,19 +82,50 @@
|
|||||||
"type": "mobile-drawer",
|
"type": "mobile-drawer",
|
||||||
"children": [
|
"children": [
|
||||||
{
|
{
|
||||||
"id": "e3c9f68a35edf017",
|
"id": "74ab9d565ea062c4",
|
||||||
|
"type": "tabs",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "bcf01574fb3a7a3b",
|
||||||
"type": "leaf",
|
"type": "leaf",
|
||||||
"state": {
|
"state": {
|
||||||
"type": "backlink",
|
"type": "backlink",
|
||||||
"state": {
|
"state": {
|
||||||
"file": "00. TOP/01. TODO.md",
|
"file": "00. TOP/01. TODO.md",
|
||||||
"collapseAll": false,
|
"collapseAll": true,
|
||||||
"extraContext": false,
|
"extraContext": true,
|
||||||
"sortOrder": "alphabetical",
|
"sortOrder": "alphabetical",
|
||||||
"showSearch": false,
|
"showSearch": false,
|
||||||
"searchQuery": "",
|
"searchQuery": "",
|
||||||
"backlinkCollapsed": false,
|
"backlinkCollapsed": false,
|
||||||
"unlinkedCollapsed": true
|
"unlinkedCollapsed": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "509990f938113653",
|
||||||
|
"type": "leaf",
|
||||||
|
"state": {
|
||||||
|
"type": "advanced-tables-toolbar",
|
||||||
|
"state": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "2b8688e445848e2a",
|
||||||
|
"type": "tabs",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "11f4d517d7b320b2",
|
||||||
|
"type": "leaf",
|
||||||
|
"state": {
|
||||||
|
"type": "tag",
|
||||||
|
"state": {
|
||||||
|
"sortOrder": "frequency",
|
||||||
|
"useHierarchy": true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -98,14 +135,14 @@
|
|||||||
"active": "94f0e8a81af6c9e2",
|
"active": "94f0e8a81af6c9e2",
|
||||||
"lastOpenFiles": [
|
"lastOpenFiles": [
|
||||||
"00. TOP/01. TODO.md",
|
"00. TOP/01. TODO.md",
|
||||||
"00. TOP/00. Inbox.md",
|
"02. PARA/03. Resources(資源)/C++17/rvalue.md",
|
||||||
"02. PARA/03. Resources(資源)/C++17/Class template.md",
|
"02. PARA/03. Resources(資源)/C++17/move operator.md",
|
||||||
"02. PARA/03. Resources(資源)/C++17/C++17.md",
|
"02. PARA/03. Resources(資源)/C++17/智慧指標.md",
|
||||||
"02. PARA/03. Resources(資源)/01. 架站/04. Gitea.md",
|
"02. PARA/03. Resources(資源)/git/submodule.md",
|
||||||
"02. PARA/03. Resources(資源)/Tool Setup/Obisidian.md",
|
"02. PARA/03. Resources(資源)/git.md",
|
||||||
"README.md",
|
"02. PARA/01. Project(專案)/008. Sentinel.md",
|
||||||
"test.md",
|
"02. PARA/03. Resources(資源)/C++17/lvalue.md",
|
||||||
"02. PARA/03. Resources(資源)/Proxmox VE.md",
|
"02. PARA/03. Resources(資源)/FFMPEG/01. Setup.md",
|
||||||
"02. PARA/03. Resources(資源)/01. 架站/01. Nginx Layer4 Reverse Proxy.md"
|
"02. PARA/03. Resources(資源)/FFMPEG/00. Introduction.md"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
# ME
|
# ME
|
||||||
- [ ] 作筆記:C++17 - share_ptr
|
- [x] 作筆記:C++17 - share_ptr ✅ 2022-06-06
|
||||||
- [ ] 作筆記:C++17 - R value reference與std::move
|
- [ ] 作筆記:C++17 - R value reference與std::move
|
||||||
- [ ] 作筆記:C++17 - Lambda
|
- [ ] 作筆記:C++17 - Lambda
|
||||||
- [ ] 補充英格蘭與蘇格蘭的歷史
|
- [ ] 補充英格蘭與蘇格蘭的歷史
|
||||||
@@ -8,4 +8,30 @@
|
|||||||
# WORK
|
# WORK
|
||||||
## Logitech
|
## Logitech
|
||||||
### RobotRunQA
|
### RobotRunQA
|
||||||
- [ ] 檢查Amily的test task 🛫 2022-05-30 📅 2022-06-03
|
- [x] 檢查Amily的test task 🛫 2022-05-30 📅 2022-06-03 ✅ 2022-06-06
|
||||||
|
- 改進RobotRunQA report
|
||||||
|
- TT
|
||||||
|
- [x] 在測試項目的主欄位上顯示resolution, format, fps 🛫 2022-06-06 📅 2022-06-10 ✅ 2022-06-09
|
||||||
|
- [ ] 在測試項目的主欄位上顯示test time 🛫 2022-06-06 📅 2022-06-10
|
||||||
|
- [x] test config 🛫 2022-06-06 📅 2022-06-10 ✅ 2022-06-09
|
||||||
|
- TestAllFormatsVTF
|
||||||
|
- [x] 在測試細項表格上顯示詳細說明 🛫 2022-06-06 📅 2022-06-10 ✅ 2022-06-07
|
||||||
|
- [x] Show "VideoFormats: "MaxFpsMaxResolutionOnly" to outside, let user understand the test purpose. 🛫 2022-06-06 📅 2022-06-10 ✅ 2022-06-08
|
||||||
|
- [x] List max fps of all resolution of all format on side bar of section 🛫 2022-06-06 📅 2022-06-10 ✅ 2022-06-08
|
||||||
|
- TestGpsDiff
|
||||||
|
- [ ] List all format 🛫 2022-06-06 📅 2022-06-10
|
||||||
|
|
||||||
|
# All TODOs
|
||||||
|
```tasks
|
||||||
|
not done
|
||||||
|
path does not include 2021
|
||||||
|
path does not include 2022/01
|
||||||
|
path does not include 2022/02
|
||||||
|
path does not include 2022/03
|
||||||
|
path does not include 2022/04
|
||||||
|
path does not include 02. PARA/04. Archives(歸檔)
|
||||||
|
path does not include 001. Kong
|
||||||
|
group by folder
|
||||||
|
group by filename
|
||||||
|
group by heading
|
||||||
|
```
|
||||||
48
01. Daily/2022-06-06(週一).md
Normal file
48
01. Daily/2022-06-06(週一).md
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
時間:10:21:22
|
||||||
|
|
||||||
|
### TAG
|
||||||
|
|
||||||
|
|
||||||
|
### All TODOs
|
||||||
|
```tasks
|
||||||
|
not done
|
||||||
|
path does not include 2021
|
||||||
|
path does not include 2022/01
|
||||||
|
path does not include 2022/02
|
||||||
|
path does not include 2022/03
|
||||||
|
path does not include 2022/04
|
||||||
|
path does not include 02. PARA/04. Archives(歸檔)
|
||||||
|
path does not include 001. Kong
|
||||||
|
group by folder
|
||||||
|
group by filename
|
||||||
|
group by heading
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Doing TODOs
|
||||||
|
```tasks
|
||||||
|
not done
|
||||||
|
has start date
|
||||||
|
happens before tomorrow
|
||||||
|
path does not include 2021
|
||||||
|
path does not include 2022/01
|
||||||
|
path does not include 2022/02
|
||||||
|
path does not include 2022/03
|
||||||
|
path does not include 2022/04
|
||||||
|
path does not include 02. PARA/04. Archives(歸檔)
|
||||||
|
path does not include 001. Kong
|
||||||
|
group by folder
|
||||||
|
group by filename
|
||||||
|
group by heading
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 新增TODO
|
||||||
|
#### 私事
|
||||||
|
|
||||||
|
#### 公事
|
||||||
|
|
||||||
|
### 今日回顧
|
||||||
|
趁著早上還算是不太厭世,趕快來清一下TODO,先把簡單的shared_ptr寫一寫。
|
||||||
@@ -11,7 +11,7 @@ path does not include 2022/01
|
|||||||
path does not include 2022/02
|
path does not include 2022/02
|
||||||
path does not include 2022/03
|
path does not include 2022/03
|
||||||
path does not include 2022/04
|
path does not include 2022/04
|
||||||
path does not include 004 - Archives(歸檔)
|
path does not include 02. PARA/04. Archives(歸檔)
|
||||||
path does not include 001. Kong
|
path does not include 001. Kong
|
||||||
group by folder
|
group by folder
|
||||||
group by filename
|
group by filename
|
||||||
@@ -30,7 +30,7 @@ path does not include 2022/01
|
|||||||
path does not include 2022/02
|
path does not include 2022/02
|
||||||
path does not include 2022/03
|
path does not include 2022/03
|
||||||
path does not include 2022/04
|
path does not include 2022/04
|
||||||
path does not include 004 - Archives(歸檔)
|
path does not include 02. PARA/04. Archives(歸檔)
|
||||||
path does not include 001. Kong
|
path does not include 001. Kong
|
||||||
group by folder
|
group by folder
|
||||||
group by filename
|
group by filename
|
||||||
|
|||||||
@@ -1,2 +1,3 @@
|
|||||||
|
lvalue 是指:
|
||||||
- 等號左邊的值
|
- 等號左邊的值
|
||||||
- 「有固定address」的變數
|
- 可以被「取址」的變數
|
||||||
@@ -1,9 +1,210 @@
|
|||||||
|
rvalue 是指:
|
||||||
- 等號右邊的值
|
- 等號右邊的值
|
||||||
- 臨時的值,例如運算的結果
|
- 臨時的值,例如運算的結果
|
||||||
|
- 無法被取址(address-of)的物件
|
||||||
|
|
||||||
# rvalue參考
|
## rvalue reference
|
||||||
可以用兩個`&`來參考rvalue。例如:
|
一般的參考只能參考[[lvalue]],如下的程式是ok的:
|
||||||
|
```cpp
|
||||||
|
int a = 10;
|
||||||
|
int& b = a;
|
||||||
```
|
```
|
||||||
int c{5};
|
|
||||||
int&& rtepm {c + 3};
|
但是像這樣就不行了:
|
||||||
|
```cpp
|
||||||
|
int a = 10;
|
||||||
|
int b = 5;
|
||||||
|
int& c = a + b;
|
||||||
```
|
```
|
||||||
|
|
||||||
|
因為`a+b`是一個 rvalue(臨時的值,沒辦法取址),所以無法參考。
|
||||||
|
但是可以用`&&`來參考 rvalue。例如:
|
||||||
|
```cpp
|
||||||
|
int a = 10;
|
||||||
|
int b = 5;
|
||||||
|
int&& c = a + b; // c = 15
|
||||||
|
```
|
||||||
|
|
||||||
|
而不用這樣:
|
||||||
|
```cpp
|
||||||
|
int a = 10;
|
||||||
|
int b = 5;
|
||||||
|
int r = a + b;
|
||||||
|
int& c = r;
|
||||||
|
```
|
||||||
|
|
||||||
|
了解 rvalue reference 之後,就可以實作類別的 move constructor 跟 move assignment operator。這可以減少複製的成本。
|
||||||
|
|
||||||
|
## Move constructor
|
||||||
|
假設我們有一個 class 叫 BigBuffer,定義如下:
|
||||||
|
```cpp
|
||||||
|
class BigBuffer {
|
||||||
|
public:
|
||||||
|
BigBuffer(int size=100*1024*1024) :
|
||||||
|
bufferSize(size)
|
||||||
|
{
|
||||||
|
std::cout << "BigBuffer constructor\n";
|
||||||
|
this->buffer = std::make_unique<uint8_t[]>(bufferSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
~BigBuffer() {
|
||||||
|
std::cout << "BigBuffer destructor\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
BigBuffer(const BigBuffer& src) {
|
||||||
|
std::cout << "BigBuffer copy constructor\n";
|
||||||
|
bufferSize = src.bufferSize;
|
||||||
|
buffer = std::make_unique<uint8_t[]>(bufferSize);
|
||||||
|
std::memcpy(buffer.get(), src.buffer.get(), bufferSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
BigBuffer& operator= (BigBuffer& src) {
|
||||||
|
std::cout << "BigBuffer copy operator\n";
|
||||||
|
bufferSize = src.bufferSize;
|
||||||
|
buffer = std::make_unique<uint8_t[]>(bufferSize);
|
||||||
|
std::memcpy(buffer.get(), src.buffer.get(), bufferSize);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int bufferSize = 0;
|
||||||
|
std::unique_ptr<uint8_t[]> buffer = nullptr;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
這個 class 的特色就是每一次使用都會佔用100MB的記憶體空間,想像下面的程式的動作:
|
||||||
|
```cpp
|
||||||
|
BigBuffer buf1;
|
||||||
|
// Do something with buf1
|
||||||
|
// Assign to buf2
|
||||||
|
BigBuffer buf2 = buf1;
|
||||||
|
```
|
||||||
|
|
||||||
|
執行訊息:
|
||||||
|
```
|
||||||
|
BigBuffer constructor // create buf1
|
||||||
|
BigBuffer copy constructor, copy 104857600Bytes // copy buf1 to buf2
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
這會先產生 buf1,然後把 buf1 copy 給 buf2。如果我們想要省下 copy 的成本,這時候 Move constructor 就可以派上用場了。
|
||||||
|
幫 BigBuffer 加一個 Move constructor:
|
||||||
|
```cpp
|
||||||
|
class BigBuffer {
|
||||||
|
public:
|
||||||
|
...
|
||||||
|
|
||||||
|
BigBuffer(BigBuffer&& src) noexcept {
|
||||||
|
std::cout << "BigBuffer move constructor\n";
|
||||||
|
bufferSize = src.bufferSize;
|
||||||
|
buffer = std::move(src.buffer);
|
||||||
|
|
||||||
|
src.buffer.reset();
|
||||||
|
src.bufferSize = 0;
|
||||||
|
}
|
||||||
|
...
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
這個 move constructor 的參數就是一個 rvalue reference,我們把來源的 bufferSize 跟 buffer 指標「移到」我們這邊,而不是完整的複製一份。在轉移之後呢,當然也要把來源清空,讓轉移更加明確。
|
||||||
|
|
||||||
|
有了 Move assignment operator 之後,在執行一次原本的程式,你會發現訊息......沒有變,還是一樣呼叫 copy constructor 來複製了100MB 的 buffer,這時我們需要明確的告訴 compiler 我們要「移動」物件,而不是複製它,把原本的程式改為:
|
||||||
|
```cpp
|
||||||
|
BigBuffer buf1;
|
||||||
|
// Do something with buf1
|
||||||
|
// Assign to buf2
|
||||||
|
BigBuffer buf2 = std::move(buf1);
|
||||||
|
```
|
||||||
|
|
||||||
|
我們用 `std::move()` 來「移動」物件,這時輸出變成
|
||||||
|
```
|
||||||
|
BigBuffer constructor // create buf1
|
||||||
|
BigBuffer move constructor // move buf1 to buf2, buf1 has nullptr now
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
另外一個情形也可以受益於此,假如我們有個 function 會產生 `BigBuffer`,如下:
|
||||||
|
```cpp
|
||||||
|
BigBuffer BigBufferCreator() {
|
||||||
|
std::cout << "BigBufferCreator: Create a BigBuffer!\n";
|
||||||
|
BigBuffer tempb;
|
||||||
|
// do something
|
||||||
|
std::cout << "BigBufferCreator: return\n";
|
||||||
|
return tempb;
|
||||||
|
}
|
||||||
|
|
||||||
|
BigBuffer b = BigBufferCreator(); // copy tempb to b
|
||||||
|
```
|
||||||
|
|
||||||
|
在沒有 Move constructor 的情況下,上面的程式會先產生一個 `tempb`,然後複製給 `b`,訊息:
|
||||||
|
```
|
||||||
|
BigBufferCreator: Create a BigBuffer!
|
||||||
|
BigBuffer constructor
|
||||||
|
BigBufferCreator: return
|
||||||
|
BigBuffer copy constructor, copy 104857600Bytes // Copy 100MB!
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
在有 Move constructor 的情況下,訊息就變成:
|
||||||
|
```
|
||||||
|
BigBufferCreator: Create a BigBuffer!
|
||||||
|
BigBuffer constructor
|
||||||
|
BigBufferCreator: return
|
||||||
|
BigBuffer move constructor // Use MOVE!
|
||||||
|
BigBuffer destructor
|
||||||
|
BigBuffer destructor
|
||||||
|
```
|
||||||
|
|
||||||
|
因為 `BigBufferCreator()` 產生的就是一個 `BigBuffer` rvalue,所以 compiler 會使用 move constructor(`BigBuffer(BigBuffer&& src)`) 而不是 copy constructor。
|
||||||
|
|
||||||
|
## Move assignment operator(`=`)
|
||||||
|
Move assignment operator 的行為跟 move constructor 是一樣的,幫 `BigBuffer` 加入 move assignment operator:
|
||||||
|
```cpp
|
||||||
|
class BigBuffer {
|
||||||
|
public:
|
||||||
|
...
|
||||||
|
|
||||||
|
BigBuffer& operator=(BigBuffer&& src) noexcept {
|
||||||
|
std::cout << "BigBuffer move operator\n";
|
||||||
|
bufferSize = src.bufferSize;
|
||||||
|
buffer = std::move(src.buffer);
|
||||||
|
|
||||||
|
src.buffer.reset();
|
||||||
|
src.bufferSize = 0;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
...
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
測試程式:
|
||||||
|
```cpp
|
||||||
|
BigBuffer b1, b2;
|
||||||
|
b2 = b1;
|
||||||
|
```
|
||||||
|
|
||||||
|
訊息:
|
||||||
|
```
|
||||||
|
BigBuffer constructor
|
||||||
|
BigBuffer constructor
|
||||||
|
BigBuffer copy operator, copy 104857600Bytes
|
||||||
|
```
|
||||||
|
|
||||||
|
還是使用 copy assignment operator 來複製,理由是一樣的,需要一個明確的 `std::move()` 來表示「轉移」的行動,把程式改成:
|
||||||
|
```cpp
|
||||||
|
BigBuffer b1, b2;
|
||||||
|
b2 = std::move(b1);
|
||||||
|
```
|
||||||
|
|
||||||
|
這樣就可以了。訊息:
|
||||||
|
```
|
||||||
|
BigBuffer constructor
|
||||||
|
BigBuffer constructor
|
||||||
|
BigBuffer move operator // Use MOVE!
|
||||||
|
```
|
||||||
|
|
||||||
|
## 參考
|
||||||
|
- [Value categories - cppreference.com](https://en.cppreference.com/w/cpp/language/value_category)
|
||||||
|
- [rvalue 參考](https://openhome.cc/Gossip/CppGossip/RvalueReference.html)
|
||||||
|
- [Move constructors - cppreference.com](https://en.cppreference.com/w/cpp/language/move_constructor)
|
||||||
|
- [Move assignment operator - cppreference.com](https://en.cppreference.com/w/cpp/language/move_assignment)
|
||||||
|
|||||||
110
02. PARA/03. Resources(資源)/C++17/智慧指標.md
Normal file
110
02. PARA/03. Resources(資源)/C++17/智慧指標.md
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
[`unique_ptr`](https://en.cppreference.com/w/cpp/memory/unique_ptr)與[`shared_ptr`](https://en.cppreference.com/w/cpp/memory/shared_ptr)都是智慧指標,箱對於原本的raw pointer,智慧指標使用起來更方便,也不用擔心delete的問題。
|
||||||
|
|
||||||
|
## unique_ptr
|
||||||
|
`unique_ptr` 的特點是,它保證在一個時間內,只會有一個指標的擁有者,也就是這個指標不能被複製跟移動,當 `unique_ptr` 離開它的scope時候,它所擁有的指標也隨之被delete。這讓你不用擔心memory leak的問題。
|
||||||
|
假設我們有一個class叫 `BigBuffer` ,原本分配記憶體的方法:
|
||||||
|
```cpp
|
||||||
|
BigBuffer* bigBuf = new BigBuffer(bufferSize);
|
||||||
|
// Use buffer here
|
||||||
|
delete bigBuf;
|
||||||
|
```
|
||||||
|
|
||||||
|
用 `unique_ptr`:
|
||||||
|
```cpp
|
||||||
|
auto bigBuf = std::make_unique<BigBuffer>(bufferSize);
|
||||||
|
// Use buffer here
|
||||||
|
// bigBuf will be released when exiting scope
|
||||||
|
```
|
||||||
|
|
||||||
|
我們統一用[`std::make_unique<>`](https://en.cppreference.com/w/cpp/memory/unique_ptr/make_unique)這個template function來建立 `unique_ptr` ,角括號 `<>` 裡面要帶入你要建立的型別,後面的括號 `()` 就是型別的constructor,使用起來跟 `new` 是一樣的。
|
||||||
|
因為 `std::make_unique<>` 裡面已經有表明型別了,所以變數就用 `auto` 就可以了,不用再寫一次型別。
|
||||||
|
|
||||||
|
一旦 `unique_ptr` 建立之後,使用起來就跟一般指標沒有兩樣,都是用 `->` 來操作:`bigBuf->setXXX()` or `bigBuf->getXXX()`。
|
||||||
|
但是別忘記 `unique_ptr` 本身還是一個local variable,所以我們可以用 `.` 來操作 `unique_ptr` ,例如我們可以用 `.reset()` 重新配一個指標:
|
||||||
|
```cpp
|
||||||
|
BigBuffer* pBuffer = new BigBuffer();
|
||||||
|
bigBuf.reset(pBuffer);
|
||||||
|
```
|
||||||
|
這時候舊指標會自動delete,如果記憶體分配有成功的話,bigBuf會接管剛剛new出來的指標,或者變成 `nullptr` (記憶體分配失敗)。
|
||||||
|
|
||||||
|
如果單純想要釋放指標,那就單純的呼叫 `reset()` 就好。
|
||||||
|
```cpp
|
||||||
|
bigBuf.reset(); // Now I'm nullptr
|
||||||
|
```
|
||||||
|
|
||||||
|
如果要分配陣列的話:
|
||||||
|
```cpp
|
||||||
|
auto intArray = std::make_unique<int[]>(1024);
|
||||||
|
```
|
||||||
|
|
||||||
|
使用方式也是一樣的:
|
||||||
|
```cpp
|
||||||
|
intArray[5] = 555;
|
||||||
|
```
|
||||||
|
|
||||||
|
不過對於陣列的操作更建議使用 `std::array` 。
|
||||||
|
|
||||||
|
如果有什麼特殊原因讓你決定不再讓 `unique_ptr` 來幫你管理指標,可以用 `release()` 來讓出指標:
|
||||||
|
```cpp
|
||||||
|
auto intArray = std::make_unique<int[]>(1024);
|
||||||
|
int* intArrayRaw = intArray.release(); // Now I don't care anymore
|
||||||
|
```
|
||||||
|
但是這時候呼叫 `delete[]` (或 `delete` )的責任又回到你身上了。所以千萬不要把 `release()` 跟 `reset()` 搞混了。
|
||||||
|
|
||||||
|
`unique_ptr` 不能被複製跟移動,所以下列的寫法都編不過:
|
||||||
|
```cpp
|
||||||
|
auto ptr1 = std::make_unique<int>(5);
|
||||||
|
std::unique_ptr<int> ptr2(ptr1); // Error
|
||||||
|
std::unique_ptr<int> ptr2 = ptr1; // Error
|
||||||
|
```
|
||||||
|
在Visual Studio 2017上,錯誤訊息是這樣:`error C2280: 'std::unique_ptr<int,std::default_delete<int>>::unique_ptr(const std::unique_ptr<int,std::default_delete<int>> &)': attempting to reference a deleted function`。
|
||||||
|
其實就是`unique_ptr`的copy constructor跟assignment operator都被標記為delete了。
|
||||||
|
|
||||||
|
### Move a unique_ptr
|
||||||
|
如果一定要把 unique_ptr 指定給別人可以嗎?可以的,用 `std::move()` 來轉移:
|
||||||
|
```cpp
|
||||||
|
auto ptr1 = std::make_unique<int>(5);
|
||||||
|
// do something
|
||||||
|
auto anotherPtr = std::move(ptr1);
|
||||||
|
```
|
||||||
|
|
||||||
|
ptr1原本所管理的指標會轉移給 anotherPtr,ptr1 會變成 nullptr。
|
||||||
|
|
||||||
|
## shared_ptr
|
||||||
|
建立一個 `shared_ptr` 是使用[`std::make_shared()`](https://en.cppreference.com/w/cpp/memory/shared_ptr/make_shared):
|
||||||
|
```cpp
|
||||||
|
auto myBuf = std::make_shared<BigBuffer>(bufferSize);
|
||||||
|
```
|
||||||
|
|
||||||
|
但是 `shared_ptr` 可以被複製與移動,這是跟 `unique_ptr` 的差別:
|
||||||
|
```cpp
|
||||||
|
auto myBuf = std::make_shared<BigBuffer>(bufferSize);
|
||||||
|
|
||||||
|
std::shared_ptr<BigBuffer> bufCopy = myBuf;
|
||||||
|
```
|
||||||
|
|
||||||
|
現在 bufCopy 跟 myBuf 都指向同一個指標,他們都可以操作這個指標:
|
||||||
|
```cpp
|
||||||
|
myBuf->setZero(startAddr, endAddr);
|
||||||
|
bufCopy->setOne(startAddr, endAddr);
|
||||||
|
```
|
||||||
|
|
||||||
|
`shared_ptr` 內部有一個參考記數(reference count)來紀錄它所擁有的指標已經分享給幾個變數了,只要有變數離開了他的scope,參考記數就會減少,反之,要是像上面那樣有人複製指標,參考記數就會增加,參考記數歸0的時候,指標就會被釋放。
|
||||||
|
|
||||||
|
有了 `shared_ptr` 我們就不必擔心 delete 的責任問題:
|
||||||
|
```cpp
|
||||||
|
std::shared_ptr<BigBuffer> getBuffer(int32_t bufferSize) {
|
||||||
|
return std::make_shared<BigBuffer>(bufferSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
auto myBuf = getBuffer(1024); // new(malloc) memory
|
||||||
|
// use myBuf
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
} // myBuf delete memory here
|
||||||
|
```
|
||||||
|
|
||||||
|
`shared_ptr` 有一個問題是可以會「循環參考」(cyclic references),也就是 share_ptr A 指向另一個 share_ptr B ,然後 share_ptr B 又指向 share_ptr A,這造成參考記數(reference count)不會減少而永遠無法釋出指標。這個是需要注意的。
|
||||||
|
|
||||||
|
但是 `shared_ptr` 還是讓記憶體的管理問題大大減少,應該用 `shared_ptr` 來代替 `new` & `delete` 。
|
||||||
17
02. PARA/03. Resources(資源)/FFMPEG/00. Introduction.md
Normal file
17
02. PARA/03. Resources(資源)/FFMPEG/00. Introduction.md
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
- [FFmpeg](https://www.ffmpeg.org/)
|
||||||
|
- Open source
|
||||||
|
- For handling multimedia files and streams
|
||||||
|
- GPL/LGPS license
|
||||||
|
- Inspired by MPEG(Moving Picture Experts Group), FF means "Fast Foward"
|
||||||
|
- Libraries
|
||||||
|
- libavcodec: Contain all the encoders and decoders
|
||||||
|
- libavformat: Muxers and demuxers
|
||||||
|
- libavfilter: Filters that you can use on your video and audio according to your requirements
|
||||||
|
- libavdevice: Input and output devices
|
||||||
|
- libavutil
|
||||||
|
- libswscale
|
||||||
|
- libswresample
|
||||||
|
- Tools
|
||||||
|
- ffmpeg: Main transcoding engine
|
||||||
|
- ffplay: Minimum tool to play a video or audio
|
||||||
|
- ffprobe: For inspecting medias and extract valuable information
|
||||||
30
02. PARA/03. Resources(資源)/FFMPEG/01. Setup.md
Normal file
30
02. PARA/03. Resources(資源)/FFMPEG/01. Setup.md
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
FFmpeg doesn't support any official builds for any operation systems. You can build the codes from source, or use the prebuilt packages.
|
||||||
|
|
||||||
|
## From source
|
||||||
|
Get source code from [snapshot](https://ffmpeg.org/releases/ffmpeg-snapshot.tar.bz2) or git(`git clone https://git.ffmpeg.org/ffmpeg.git ffmpeg`).
|
||||||
|
|
||||||
|
## From prebuilt packages
|
||||||
|
### MacOS
|
||||||
|
Use homebrew to install FFMPEG package
|
||||||
|
```
|
||||||
|
brew install ffmpeg
|
||||||
|
```
|
||||||
|
|
||||||
|
### Ubuntu
|
||||||
|
```
|
||||||
|
sudo apt update ;\
|
||||||
|
sudo apt install ffmpeg
|
||||||
|
```
|
||||||
|
|
||||||
|
### Windows
|
||||||
|
Goto https://www.ffmpeg.org/download.html, and
|
||||||
|
![[Pasted image 20220607105807.png]]
|
||||||
|
|
||||||
|
And then browser jumps to https://www.gyan.dev/ffmpeg/builds/, click [release build](https://www.gyan.dev/ffmpeg/builds/#release-builds), download **release-full**.
|
||||||
|
![[Pasted image 20220607110211.png]]
|
||||||
|
|
||||||
|
Unzip the file, then put the folder to anywhere you like, e.g. `C:\libs`, so the full path of ffmpeg packages should looks like: `C:\libs\ffmpeg-5.0.1-full_build`
|
||||||
|
|
||||||
|
#### Add to system variable
|
||||||
|
Add the path of bin of ffmpeg packages to `PATH` system variable.
|
||||||
|
![[Pasted image 20220607110949.png]]
|
||||||
27
02. PARA/03. Resources(資源)/git/submodule.md
Normal file
27
02. PARA/03. Resources(資源)/git/submodule.md
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
## 建立 Git Submodule
|
||||||
|
```
|
||||||
|
git submodule add <repository> [<local_path>]
|
||||||
|
```
|
||||||
|
新增之後,用 git status 會發現多了兩個東西需要 commit:
|
||||||
|
![[Pasted image 20220608152709.png]]
|
||||||
|
|
||||||
|
第一個檔案 .gitmodules,裡面紀錄 submodule 的對應關係,內容大概像這樣:
|
||||||
|
```
|
||||||
|
[submodule "RobotRunQA"]
|
||||||
|
path = RobotRunQA
|
||||||
|
url = git@github.com-logi:JuiwenHsu/RobotRunQA.git
|
||||||
|
```
|
||||||
|
|
||||||
|
接下來剩3個步驟:
|
||||||
|
1. 提交 `.gitmodule`:`git add .gitmodule ; git push origin master`
|
||||||
|
2. 跟git說我們有新增一個submodule:`git submodule init`
|
||||||
|
3. 把submodule pull下來:`git submodule update`
|
||||||
|
|
||||||
|
## Clone repository and submodule
|
||||||
|
當clone一個有submodule的repo的時候,我們還需要 `git submodule init` 跟 `git submodule update` ,例如:
|
||||||
|
```
|
||||||
|
git clone https://xxx/xxx.git
|
||||||
|
cd xxx
|
||||||
|
git submodule init
|
||||||
|
git submodule update
|
||||||
|
```
|
||||||
BIN
attachments/Pasted image 20220607105807.png
Normal file
BIN
attachments/Pasted image 20220607105807.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 70 KiB |
BIN
attachments/Pasted image 20220607110211.png
Normal file
BIN
attachments/Pasted image 20220607110211.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 73 KiB |
BIN
attachments/Pasted image 20220607110949.png
Normal file
BIN
attachments/Pasted image 20220607110949.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 70 KiB |
BIN
attachments/Pasted image 20220608152709.png
Normal file
BIN
attachments/Pasted image 20220608152709.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 23 KiB |
Reference in New Issue
Block a user