首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

VS2010 中常用 C++11 特性實戰速查:static_assert、decltype、auto、Lambda、右值引用與移動語義

     編輯:關於C++

1. static_assert — 編護期斷言

constexpr int MAX_SIZE = 100;
static_assert(MAX_SIZE > 10, "Buffer too small"); // 編譯失敗若條件為假
static_assert(sizeof(void*) == 8, "64-bit required");

優於 #error:可依賴模板參數、constexpr 函數結果,錯誤信息可定制。

2. decltype — 表達式類型推導

int x = 0;
decltype(x) y = 10;           // int
decltype((x)) z = y;          // int& (加括號 → 引用類型)
decltype(x + y) w = 0;        // int (表達式非左值)

// 尾置返回類型配合 decltype
template <typename T, typename U>
auto add(T a, U b) -> decltype(a + b) { return a + b; }

規則:decltype(var) 保留 cv/引用;decltype(expr) 表達式為左值則得 T&,右值得 T。

3. auto — 變量類型自動推導

auto i = 42;          // int
auto d = 3.14;        // double
auto p = new auto(10); // int* (C++11 支持 new auto)
auto& ref = i;        // int&
const auto& cref = i; // const int&

// 範圍 for 配合 auto
for (auto& x : vec) x *= 2;
for (const auto& x : vec) cout << x; // 僅讀用 const&

VS2010 限制:不支持 new auto(expr) 動態分配語法,會報錯誤。

4. Lambda 表達式 — 就地函數對象

// 基本語法:[捕獲列表](參數)->返回類型 { 函數體 }
auto add = [](int a, int b) { return a + b; }; // 返回類型自動推導
auto greet = [](const string& name) -> string { return "Hello " + name; };

// 捕獲列表
int factor = 10;
auto scale = [factor](int x) { return x * factor; }; // 值捕獲
auto scaleRef = [&factor](int x) { return x * factor; } // 引用捕獲
auto allVal = [=](int x) { return x * factor; } // 全部值捕獲
auto allRef = [&](int x) { return x * factor; } // 全部引用捕獲

// STL 算法中使用
vector v = {3,1,4,1,5};
sort(v.begin(), v.end(), [](int a, int b){ return a > b; }); // 降序
int cnt = count_if(v.begin(), v.end(), [](int x){ return x % 2 == 0; });

5. 右值引用與移動語義 — 消除無用拷貝

左值 vs 右值

  • 左值:有名字、可取地址、生命週期超過單表達式。
  • 右值:臨時對象、字面量、std::move(x) 轉換結果。

移動構造/移動賦值

class String {
    char* data; size_t len;
public:
    String(const char* s) : len(strlen(s)) { data = new char[len+1]; strcpy(data, s); }
    // 移動構造:竊取資源,置空源對象
    String(String&& other) noexcept : data(other.data), len(other.len) {
        other.data = nullptr; other.len = 0;
    }
    // 移動賦值
    String& operator=(String&& other) noexcept {
        if (this != &other) {
            delete[] data;
            data = other.data; len = other.len;
            other.data = nullptr; other.len = 0;
        }
        return *this;
    }
    ~String() { delete[] data; }
};

std::move 與 std::forward

String s1("hello");
String s2 = std::move(s1); // 調用移動構造,s1 置空

// 完美轉發:保持實參左/右值屬性
template <typename T>
void wrapper(T&& arg) {
    foo(std::forward<T>(arg)); // 左值傳左值,右值傳右值
}

VS2010 實現細節:std::move 利用 _Remove_reference traits 去除引用再加 &&;std::forward 利用 identity 保持類型不變。

避坑清單

  • 移動操作標記 noexcept,否則 STL 容器擴容時會退回拷貝。
  • 移動後源對象必須置於有效但未指定狀態(通常置空指針、歸零長度)。
  • Lambda 捕獲 this 時注意對象生命週期,避免懸空指針。
  • auto 推導 initializer_list 時需顯式指定:auto x = {1,2}; // std::initializer_list。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved