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/日記"
|
||||
}
|
||||
121
.obsidian/workspace
vendored
121
.obsidian/workspace
vendored
@@ -11,7 +11,7 @@
|
||||
"type": "markdown",
|
||||
"state": {
|
||||
"file": "00. TOP/01. TODO.md",
|
||||
"mode": "source",
|
||||
"mode": "preview",
|
||||
"source": true
|
||||
}
|
||||
}
|
||||
@@ -35,25 +35,31 @@
|
||||
"type": "mobile-drawer",
|
||||
"children": [
|
||||
{
|
||||
"id": "88e1cff7a30f6953",
|
||||
"type": "leaf",
|
||||
"state": {
|
||||
"type": "file-explorer",
|
||||
"state": {}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "ceb171daf1327c40",
|
||||
"type": "leaf",
|
||||
"state": {
|
||||
"type": "search",
|
||||
"state": {
|
||||
"query": "",
|
||||
"matchingCase": false,
|
||||
"explainSearch": false,
|
||||
"collapseAll": false,
|
||||
"extraContext": false,
|
||||
"sortOrder": "alphabetical"
|
||||
"id": "dbd6f1d450f54a18",
|
||||
"type": "tabs",
|
||||
"children": [
|
||||
{
|
||||
"id": "f0c230180a9faaa1",
|
||||
"type": "leaf",
|
||||
"state": {
|
||||
"type": "file-explorer",
|
||||
"state": {}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "81a47da514b9d823",
|
||||
"type": "leaf",
|
||||
"state": {
|
||||
"type": "search",
|
||||
"state": {
|
||||
"query": "shared_ptr",
|
||||
"matchingCase": false,
|
||||
"explainSearch": false,
|
||||
"collapseAll": false,
|
||||
"extraContext": false,
|
||||
"sortOrder": "alphabetical"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -76,19 +82,50 @@
|
||||
"type": "mobile-drawer",
|
||||
"children": [
|
||||
{
|
||||
"id": "e3c9f68a35edf017",
|
||||
"type": "leaf",
|
||||
"state": {
|
||||
"type": "backlink",
|
||||
"state": {
|
||||
"file": "00. TOP/01. TODO.md",
|
||||
"collapseAll": false,
|
||||
"extraContext": false,
|
||||
"sortOrder": "alphabetical",
|
||||
"showSearch": false,
|
||||
"searchQuery": "",
|
||||
"backlinkCollapsed": false,
|
||||
"unlinkedCollapsed": true
|
||||
"id": "74ab9d565ea062c4",
|
||||
"type": "tabs",
|
||||
"children": [
|
||||
{
|
||||
"id": "bcf01574fb3a7a3b",
|
||||
"type": "leaf",
|
||||
"state": {
|
||||
"type": "backlink",
|
||||
"state": {
|
||||
"file": "00. TOP/01. TODO.md",
|
||||
"collapseAll": true,
|
||||
"extraContext": true,
|
||||
"sortOrder": "alphabetical",
|
||||
"showSearch": false,
|
||||
"searchQuery": "",
|
||||
"backlinkCollapsed": false,
|
||||
"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",
|
||||
"lastOpenFiles": [
|
||||
"00. TOP/01. TODO.md",
|
||||
"00. TOP/00. Inbox.md",
|
||||
"02. PARA/03. Resources(資源)/C++17/Class template.md",
|
||||
"02. PARA/03. Resources(資源)/C++17/C++17.md",
|
||||
"02. PARA/03. Resources(資源)/01. 架站/04. Gitea.md",
|
||||
"02. PARA/03. Resources(資源)/Tool Setup/Obisidian.md",
|
||||
"README.md",
|
||||
"test.md",
|
||||
"02. PARA/03. Resources(資源)/Proxmox VE.md",
|
||||
"02. PARA/03. Resources(資源)/01. 架站/01. Nginx Layer4 Reverse Proxy.md"
|
||||
"02. PARA/03. Resources(資源)/C++17/rvalue.md",
|
||||
"02. PARA/03. Resources(資源)/C++17/move operator.md",
|
||||
"02. PARA/03. Resources(資源)/C++17/智慧指標.md",
|
||||
"02. PARA/03. Resources(資源)/git/submodule.md",
|
||||
"02. PARA/03. Resources(資源)/git.md",
|
||||
"02. PARA/01. Project(專案)/008. Sentinel.md",
|
||||
"02. PARA/03. Resources(資源)/C++17/lvalue.md",
|
||||
"02. PARA/03. Resources(資源)/FFMPEG/01. Setup.md",
|
||||
"02. PARA/03. Resources(資源)/FFMPEG/00. Introduction.md"
|
||||
]
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
# ME
|
||||
- [ ] 作筆記:C++17 - share_ptr
|
||||
- [x] 作筆記:C++17 - share_ptr ✅ 2022-06-06
|
||||
- [ ] 作筆記:C++17 - R value reference與std::move
|
||||
- [ ] 作筆記:C++17 - Lambda
|
||||
- [ ] 補充英格蘭與蘇格蘭的歷史
|
||||
@@ -8,4 +8,30 @@
|
||||
# WORK
|
||||
## Logitech
|
||||
### 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/03
|
||||
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
|
||||
group by folder
|
||||
group by filename
|
||||
@@ -30,7 +30,7 @@ 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 004 - Archives(歸檔)
|
||||
path does not include 02. PARA/04. Archives(歸檔)
|
||||
path does not include 001. Kong
|
||||
group by folder
|
||||
group by filename
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
lvalue 是指:
|
||||
- 等號左邊的值
|
||||
- 「有固定address」的變數
|
||||
- 可以被「取址」的變數
|
||||
@@ -1,9 +1,210 @@
|
||||
rvalue 是指:
|
||||
- 等號右邊的值
|
||||
- 臨時的值,例如運算的結果
|
||||
- 無法被取址(address-of)的物件
|
||||
|
||||
# rvalue參考
|
||||
可以用兩個`&`來參考rvalue。例如:
|
||||
## rvalue reference
|
||||
一般的參考只能參考[[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