企業(yè)做的網(wǎng)站推廣方案的步驟深圳網(wǎng)站建設哪家好
每日一題
200. 島嶼數(shù)量
class Solution
{//使用深度的優(yōu)先搜索來搜索島嶼圖//遍歷整個圖片 當char數(shù)組的值為1時開始從這個點開始往外擴散搜索//注意處理邊界 圖不是正方形
public:int ans;int d[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};int N;int M;void dfs(vector<vector<char>> &grid, vector<vector<int>> &vis, int i, int j){for (int k = 0; k < 4; k++){int nx = i + d[k][0];int ny = j + d[k][1];if (nx < 0 || nx > N - 1 || ny < 0 || ny > M - 1)continue;if (!vis[nx][ny]&& grid[nx][ny] != '0'){vis[nx][ny] = 1;dfs(grid, vis, nx, ny);}}}int numIslands(vector<vector<char>> &grid){ans = 0;N = grid.size();M = grid[0].size();vector<vector<int>> vis(N, vector<int>(M, 0));for (int i = 0; i < N; i++){for (int j = 0; j < M; j++){if (!vis[i][j] && grid[i][j] != '0'){ans++;vis[i][j] = 1;dfs(grid, vis, i, j);}}}return ans;}
};
C++11新特性
自動類型推導(auto 和 decltype):
????????在C++中,自動類型推導是通過auto
和decltype
來實現(xiàn)的。這些關鍵字讓程序員能夠在不顯式指定類型的情況下,依賴編譯器自動推導出變量的類型
auto
:
auto
關鍵字用于自動推導變量的類型。編譯器根據(jù)初始化表達式的類型來推導變量的類型。- 它使得代碼更加簡潔,尤其是在聲明復雜類型(如迭代器或lambda表達式)時非常有用。
- 使用示例:
-
auto x = 42; // x的類型是int auto y = 3.14; // y的類型是double auto ptr = new int(10); // ptr的類型是int*
decltype
:
decltype
關鍵字用于推導一個表達式的類型,但與auto
不同的是,decltype
是在編譯時對表達式類型的靜態(tài)分析,返回的是表達式的實際類型。- 它常用于模板編程,或者當你想要獲得某個表達式類型但又不確定時非常有用。
- 使用示例:
-
int x = 42; decltype(x) y = 10; // y的類型是int,與x相同
右值引用和移動語義:
????????右值引用和移動語義是C++11引入的重要特性,用來優(yōu)化資源管理,尤其是在處理動態(tài)分配內(nèi)存、數(shù)組、容器等時,避免不必要的深拷貝。
右值引用:
-
右值引用是通過
&&
符號表示的,允許我們綁定到右值(臨時對象、即將銷毀的對象)上。 -
在傳統(tǒng)的C++中,右值只能綁定到常量或臨時變量,但通過右值引用,程序員可以顯式地“轉(zhuǎn)移”對象的所有權。
-
右值引用通常與移動語義一起使用,使得對象的資源(如內(nèi)存、文件句柄等)能夠從一個對象轉(zhuǎn)移到另一個對象,而不是進行深拷貝。
-
使用示例:
-
int&& r = 10; // r是右值引用,綁定到臨時值10
移動語義:
-
移動語義允許對象的資源(如內(nèi)存或文件句柄)在不進行深拷貝的情況下,從一個對象“移動”到另一個對象。
-
通過實現(xiàn)移動構造函數(shù)和移動賦值運算符,C++能夠通過右值引用有效地轉(zhuǎn)移資源而不是復制。
-
在標準庫容器(如
std::vector
、std::string
)中,移動語義顯著提高了性能,因為容器可以直接將元素從一個容器轉(zhuǎn)移到另一個容器,而不需要復制每個元素。 -
使用示例:
-
class MyClass { public:MyClass(int size) : data(new int[size]) {}~MyClass() { delete[] data; }// 移動構造函數(shù)MyClass(MyClass&& other) noexcept : data(other.data) {other.data = nullptr;}// 移動賦值運算符MyClass& operator=(MyClass&& other) noexcept {if (this != &other) {delete[] data;data = other.data;other.data = nullptr;}return *this;}private:int* data; };
詳解等于號運算符重載實現(xiàn)移動語義?
MyClass& operator=(MyClass&& other) noexcept {if (this != &other) {delete[] data; // 1data = other.data; // 2other.data = nullptr; // 3}return *this; // 4
}
1. if (this != &other)
這行代碼用來確保我們沒有將一個對象賦值給它自己。我們需要避免以下的情況:
obj1 = std::move(obj1); // 這樣就會發(fā)生自賦值
如果this
和&other
是相同的(即它們指向的是同一個對象),那么在移動操作時會導致對象的資源被錯誤地釋放,最終使得對象處于不一致的狀態(tài)。因此,首先通過這個條件判斷來確保移動賦值操作不會出現(xiàn)自賦值的情況。
2. delete[] data;
這行代碼釋放當前對象的資源,尤其是類中的動態(tài)分配內(nèi)存(data
指針指向的內(nèi)存)。在進行移動賦值操作時,我們必須釋放當前對象的資源,以便為從other
對象“移動”資源做好準備。
為什么要釋放資源?
在“移動”資源之前,我們需要確保當前對象沒有持有相同的資源。假設data
指向動態(tài)分配的內(nèi)存,在data = other.data;
之后,data
和other.data
指向同一塊內(nèi)存。如果不釋放原有的內(nèi)存,就會導致內(nèi)存泄漏,因為對象this
和other
都持有相同的資源指針,但other
指針的析構時會釋放這塊內(nèi)存,導致this
的指針懸掛,出現(xiàn)不一致的行為。
3. data = other.data;
這行代碼將other
對象的data
指針賦給當前對象data
,實現(xiàn)資源的“轉(zhuǎn)移”。也就是說,我們把other
對象所管理的內(nèi)存(資源)轉(zhuǎn)移到當前對象this
上。other.data
指向原來的內(nèi)存塊,而this->data
也指向同一塊內(nèi)存塊。
此時,this
對象就擁有了other
對象的資源,other
對象中的data
指針指向了同樣的內(nèi)存,而other
對象的資源將不再有效。
4. other.data = nullptr;
在這行代碼中,我們將other.data
指針置為nullptr
。這是為了確保other
對象在析構時不會試圖釋放資源。由于我們已經(jīng)將other
對象的資源轉(zhuǎn)移給了this
,other
對象不再擁有該資源,因此將other.data
置為nullptr
可以防止其析構時錯誤地刪除內(nèi)存。
這一步是移動操作的核心,確保在移動后,other
對象不會誤操作原本應該由this
對象管理的內(nèi)存,避免多次釋放同一塊內(nèi)存。
5. return *this;
最后,返回*this
,即當前對象的引用。這是符合賦值運算符規(guī)范的做法,返回*this
允許鏈式賦值操作,例如:
a = b = c;
這里a = b = c;
首先執(zhí)行b = c;
,然后執(zhí)行a = b;
,每次都會返回賦值后的對象,以便進行下一次賦值。
為什么使用noexcept
?
noexcept
關鍵字表示這個移動賦值運算符不拋出任何異常。移動操作通常不需要動態(tài)分配內(nèi)存或者執(zhí)行復雜的操作,因此它應該是一個不會拋出異常的操作。如果移動賦值操作拋出異常,則會破壞對象狀態(tài)的一致性,并導致潛在的問題。