最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++異常處理完全指南(最新推薦)

 更新時間:2026年07月29日 09:36:23   作者:jinyishu_  
在C++中,異常處理是一項非常重要的特性,它允許程序在運行時處理錯誤情況,而不是在編譯時,異常處理通過使用try、catch、throw關(guān)鍵字來實現(xiàn),下面將詳細介紹C++中的異常處理的相關(guān)知識,感興趣的朋友一起看看吧

本文將詳細講解C++異常的拋出、捕獲、棧展開、繼承體系、重新拋出、異常安全、noexcept,最后手搓一個多模塊項目的異常處理框架。

一、為什么需要異常

1.1 C語言的痛:錯誤碼

回想一下C語言怎么處理錯誤:

// C語言風(fēng)格:用返回值表示錯誤
int Div(int a, int b, int* result) {
    if (b == 0) {
        return -1;  // 除0錯誤
    }
    *result = a / b;
    return 0;  // 成功
}
int main() {
    int result;
    int ret = Div(10, 0, &result);
    if (ret == -1) {
        printf("除0錯誤!\n");
    } else if (ret == -2) {
        printf("溢出錯誤!\n");
    }
    // 每多一種錯誤,就多一個if...查表過程非常繁瑣
}

問題很明顯:

  • 錯誤碼和正常返回值混在一起,函數(shù)的返回值被占用,只能用輸出參數(shù)傳結(jié)果
  • 錯誤碼需要查表,拿到 -1 還得去文檔查這到底是什么錯誤
  • 錯誤信息太少,除了一個數(shù)字,沒有上下文、沒有調(diào)用棧
  • 逐層傳遞噩夢A→B→C→D 調(diào)用鏈,D 出錯,C/B/A 每一層都得檢查返回值并繼續(xù)往上傳遞

1.2 異常的核心思想

C++異常機制把程序分成兩個角色:

  • 檢測方:我發(fā)現(xiàn)問題了,拋出一個對象,把錯誤信息打包扔出去,不管誰來處理
  • 處理方:我能處理這種問題,在調(diào)用鏈的高處等著,我不管誰拋出來的

核心價值:問題的檢測與問題的處理在代碼上完全分離。底層函數(shù)只管報錯,上層函數(shù)只管處理。

二、異常的基本用法:throw / try / catch

2.1 最簡示例

#include <iostream>
#include <string>
using namespace std;
double Divide(int a, int b) {
    if (b == 0) {
        string s("Divide by zero condition!");
        throw s;  // 拋出一個異常對象,函數(shù)到此為止,后面代碼不再執(zhí)行
    }
    return (double)a / (double)b;
}
int main() {
    try {
        cout << Divide(10, 0) << endl;  // 受監(jiān)控的代碼塊
    } catch (const string& errmsg) {     // 類型匹配的異常處理
        cout << "捕獲到異常:" << errmsg << endl;
    } catch (...) {                       // 兜底:捕獲任意類型
        cout << "未知異常" << endl;
    }
    return 0;
}

關(guān)鍵語義

  1. throw 執(zhí)行時,throw 后面的語句不再執(zhí)行,函數(shù)立即退出
  2. 控制權(quán)從 throw 位置直接跳轉(zhuǎn)到匹配的 catch
  3. 會生成異常對象的拷貝(因為局部對象在棧展開中會被銷毀)

2.2 多層調(diào)用鏈中的異常傳播

這是異常最體現(xiàn)威力的時候——錯誤可以跨越 N 層函數(shù):

void Func() {
    int len, time;
    cin >> len >> time;
    try {
        cout << Divide(len, time) << endl;
    } catch (const char* errmsg) {
        cout << errmsg << endl;
    }
    cout << __FUNCTION__ << ":" << __LINE__ << "行執(zhí)行" << endl;
}
int main() {
    while (1) {
        try {
            Func();
        } catch (const string& errmsg) {  // Func沒catch string類型,繼續(xù)往外找
            cout << errmsg << endl;
        } catch (...) {
            cout << "未知異常" << endl;
        }
    }
    return 0;
}

調(diào)用鏈?zhǔn)?main → Func → Divide。Divide 拋出 string 異常:

  • Divide 內(nèi)部沒有 catch string→ 退出 Divide
  • Func 中 catch 的是 const char*,不匹配 → 退出 Func
  • main 中 catch 了 const string&,匹配成功,處理異常

三、棧展開(Stack Unwinding)

上面這個"逐層退出找 catch"的過程,就叫棧展開。

調(diào)用鏈: main → Func → Divide
                         │
                      throw string ← 異常從這里拋出
                         │
                    ┌────┘
                    ▼
              Func 退出了嗎?退了!
              Func 的catch匹配嗎?不匹配!
                    │
               ┌────┘
               ▼
         main 的catch匹配嗎?匹配!→ 在這里處理

棧展開過程中會發(fā)生什么

  1. 從 throw 位置沿著調(diào)用鏈逐層退出
  2. 每退出一個函數(shù),該函數(shù)內(nèi)的局部對象都會被正確析構(gòu)(這是 RAII 的基礎(chǔ))
  3. 直到找到匹配的 catch,或者到 main 都沒找到 → 調(diào)用 std::terminate 終止程序

這意味著:即使出錯了,棧上的資源也不會泄漏——局部對象的析構(gòu)函數(shù)會被自動調(diào)用。但堆上手動 new 的資源不會自動釋放,這就是后面要講的異常安全問題。

四、異常匹配規(guī)則

4.1 精確匹配優(yōu)先

// 拋出 string
throw string("hello");
// 按順序匹配,第一個匹配的就進去
catch (int x)           { }  // 不匹配
catch (const string& s) { }  // 匹配!進入這里
catch (string s)        { }  // 雖然也匹配,但前面已經(jīng)進了
catch (...)             { }  // 兜底

4.2 允許的隱式轉(zhuǎn)換(重要!)

catch 匹配不是完全死板的,允許以下幾種轉(zhuǎn)換:

轉(zhuǎn)換類型示例說明
非 const → conststringconst string&權(quán)限縮小,安全
派生類 → 基類SqlExceptionException&最實用!繼承體系的基石
數(shù)組 → 指針char[10]char*
函數(shù) → 函數(shù)指針void()void(*)()

派生類到基類的轉(zhuǎn)換,是整個企業(yè)級異常處理體系的核心。后面我們會看到,定義一個 Exception 基類,所有模塊的異常都繼承它,外層只 catch 基類引用就能處理所有異常——多態(tài)自動分發(fā)到正確的 what()。

4.3 catch(…) 兜底

catch (...) {
    // 捕獲一切,但你不知道具體是什么
    cout << "未知異常" << endl;
}

通常放在 main 函數(shù)的最外層,防止異常沒被處理直接 terminate。正常的業(yè)務(wù)邏輯不應(yīng)該依賴它。

五、構(gòu)建企業(yè)級異常繼承體系

5.1 設(shè)計思路

一個小腳本不需要異常。但大型項目(微服務(wù)、數(shù)據(jù)庫中間件等)有多個模塊,每個模塊可能出不同錯誤:

  • SQL 模塊:權(quán)限不足、語法錯誤、連接超時
  • 緩存模塊:權(quán)限不足、數(shù)據(jù)不存在
  • HTTP 模塊:請求資源不存在、權(quán)限不足

如果每個模塊用不同的類、不同的字段,外層處理要寫幾十個 catch。更好的做法是:

定義一個基類 Exception,各模塊繼承它,外層只 catch 基類引用。

5.2 完整代碼實現(xiàn)

#include <iostream>
#include <string>
#include <thread>
using namespace std;
// ==================== 異?;?====================
class Exception {
public:
    Exception(const string& errmsg, int id)
        : _errmsg(errmsg), _id(id) {}
    virtual string what() const {
        return _errmsg;
    }
    int getid() const {
        return _id;
    }
protected:
    string _errmsg;  // 錯誤描述
    int _id;         // 錯誤編號
};
// ==================== SQL 模塊異常 ====================
class SqlException : public Exception {
public:
    SqlException(const string& errmsg, int id, const string& sql)
        : Exception(errmsg, id), _sql(sql) {}
    virtual string what() const {
        string str = "SqlException:";
        str += _errmsg;
        str += "->";
        str += _sql;       // 附上出錯的SQL語句
        return str;
    }
private:
    const string _sql;
};
// ==================== 緩存模塊異常 ====================
class CacheException : public Exception {
public:
    CacheException(const string& errmsg, int id)
        : Exception(errmsg, id) {}
    virtual string what() const {
        string str = "CacheException:";
        str += _errmsg;
        return str;
    }
};
// ==================== HTTP 模塊異常 ====================
class HttpException : public Exception {
public:
    HttpException(const string& errmsg, int id, const string& type)
        : Exception(errmsg, id), _type(type) {}
    virtual string what() const {
        string str = "HttpException:";
        str += _type;       // GET/POST/PUT
        str += ":";
        str += _errmsg;
        return str;
    }
private:
    const string _type;
};

5.3 模擬三個服務(wù)模塊

void SQLMgr() {
    if (rand() % 7 == 0) {
        throw SqlException("權(quán)限不足", 100, "select * from name = '張三'");
    }
    cout << "SQLMgr 調(diào)用成功" << endl;
}
void CacheMgr() {
    if (rand() % 5 == 0) {
        throw CacheException("權(quán)限不足", 100);
    } else if (rand() % 6 == 0) {
        throw CacheException("數(shù)據(jù)不存在", 101);
    }
    cout << "CacheMgr 調(diào)用成功" << endl;
    SQLMgr();   // Cache里面還要調(diào)SQL
}
void HttpServer() {
    if (rand() % 3 == 0) {
        throw HttpException("請求資源不存在", 100, "get");
    } else if (rand() % 4 == 0) {
        throw HttpException("權(quán)限不足", 101, "post");
    }
    cout << "HttpServer 調(diào)用成功" << endl;
    CacheMgr();  // HTTP里面調(diào)緩存,緩存里面還調(diào)SQL
}

調(diào)用鏈:main → HttpServer → CacheMgr → SQLMgr,三層嵌套

5.4 多態(tài)捕獲:一行 catch 處理所有異常

int main() {
    srand(time(0));
    while (1) {
        this_thread::sleep_for(chrono::seconds(1));
        try {
            HttpServer();
        }
        catch (const Exception& e) {  // 只catch基類引用!
            // 多態(tài)調(diào)用——根據(jù)實際對象類型調(diào)用對應(yīng)的what()
            cout << e.what() << endl;
        }
        catch (...) {
            cout << "Unknown Exception" << endl;
        }
    }
    return 0;
}

這就是繼承體系+虛函數(shù)多態(tài)的威力

  • SQL、緩存、HTTP 三個模塊,各自定義了不同的異常類
  • 但 main 里只需要一個 catch (const Exception& e)
  • 實際拋出的 SqlException 對象 → 基類引用綁定 → e.what() 多態(tài)調(diào)用 → 調(diào)用 SqlException::what()
  • 以后加新模塊(比如消息隊列模塊),只需新寫一個 MqException : public Exception,main 一行不用改

六、異常的重新拋出

6.1 問題場景

有時候 catch 到異常后,不是所有情況都能處理。比如:

  • 能處理的:網(wǎng)絡(luò)不穩(wěn)定導(dǎo)致發(fā)送失敗 → 重試幾次
  • 不能處理的:對方已不是好友 → 這個沒法重試,交給上層通知用戶

這時候需要分類處理:某種錯誤自己處理,其他錯誤重新扔出去。

6.2 語法:直接 throw;

catch (const Exception& e) {
    if (e.getid() == 102) {
        // 能處理:網(wǎng)絡(luò)問題,重試
    } else {
        throw;  // 重新拋出當(dāng)前捕獲的異常對象
    }
}

注意throw; 不加參數(shù),表示把當(dāng)前 catch 到的異常對象原樣拋出。不是 throw e;——throw e; 會生成一個新拷貝,而且如果 e 是基類引用,throw e; 會按基類類型拋出,丟失派生類信息。

6.3 實戰(zhàn):帶重試的發(fā)送消息

// 底層發(fā)送函數(shù):可能拋異常
void _SendMsg(const string& s) {
    if (rand() % 2 == 0) {
        throw HttpException("網(wǎng)絡(luò)不穩(wěn)定,發(fā)送失敗", 102, "put");     // 可重試
    } else if (rand() % 7 == 0) {
        throw HttpException("你已經(jīng)不是對方的好友,發(fā)送失敗", 103, "put");  // 不可重試
    }
    cout << "發(fā)送成功" << endl;
}
// 上層:帶重試邏輯
void SendMsg(const string& s) {
    for (size_t i = 0; i < 4; i++) {     // 最多重試3次
        try {
            _SendMsg(s);
            break;                         // 發(fā)送成功,退出循環(huán)
        }
        catch (const Exception& e) {
            if (e.getid() == 102) {       // 102號:網(wǎng)絡(luò)問題,可重試
                if (i == 3) {
                    throw;                 // 重試3次都失敗,認命,往上拋
                }
                cout << "開始第" << i + 1 << "次重試" << endl;
            } else {
                throw;                     // 不是網(wǎng)絡(luò)問題,不重試,直接往上拋
            }
        }
    }
}
// 最上層:展示結(jié)果給用戶
int main() {
    srand(time(0));
    string str;
    while (cin >> str) {
        try {
            SendMsg(str);
        }
        catch (const Exception& e) {
            cout << e.what() << endl << endl;
        }
        catch (...) {
            cout << "Unknown Exception" << endl;
        }
    }
    return 0;
}

三層分工清晰

層級職責(zé)
_SendMsg檢測問題,拋出具體異常
SendMsg分類處理:能重試的重試,不能的重新拋出
main最終兜底:通知用戶

七、異常安全問題

7.1 異常 + 裸指針 = 資源泄漏

void Func() {
    int* array = new int[10];   // ① 申請堆內(nèi)存
    int len, time;
    cin >> len >> time;
    cout << Divide(len, time) << endl;  // ② 如果這里拋異常了……
    delete[] array;             // ③ 這行根本執(zhí)行不到!
}

如果 Divide 拋出異常,delete[] array 永遠不會執(zhí)行 → 10個int的內(nèi)存泄漏。

7.2 解決方案:catch后重新拋出

void Func() {
    int* array = new int[10];
    try {
        int len, time;
        cin >> len >> time;
        cout << Divide(len, time) << endl;
    }
    catch (...) {
        // 不管什么異常,先釋放資源
        delete[] array;
        throw;  // 再把異常原樣拋出去,讓上層處理
    }
    delete[] array;
}

套路:catch 住 → 釋放自己負責(zé)的資源 → 重新 throw,讓上層繼續(xù)處理業(yè)務(wù)邏輯。

7.3 更好的方案:RAII

當(dāng)然,手動 new/delete + catch 重新拋出太容易出錯了。C++ 的最佳實踐是 RAII(Resource Acquisition Is Initialization)——用智能指針、容器等自動管理資源的類,它們在棧展開時會被自動析構(gòu),不需要手動清理。關(guān)于智能指針的內(nèi)容,我們在下一篇文章中講解。

7.4 析構(gòu)函數(shù)中的異常——千萬別讓它逃出去

~MyClass() {
    // 析構(gòu)函數(shù)要釋放10個資源
    // 如果釋放到第5個時拋異常,后面5個就泄漏了
    // 所以析構(gòu)函數(shù)內(nèi)部要做好try/catch,別讓異常逃出去
    try {
        // 釋放資源
    } catch (...) {
        // 吞掉異?;蛴涗浫罩?,但不往外拋
    }
}

八、noexcept:承諾不拋異常

8.1 C++98 的異常規(guī)范(已被歷史淘汰)

// C++98 風(fēng)格:函數(shù)后面寫 throw(可能拋的類型)
void* operator new (size_t size) throw (std::bad_alloc);   // 可能拋 bad_alloc
void* operator delete (void* ptr) throw();                   // 不拋異常
// 過于復(fù)雜,實踐中沒人用,C++11 廢棄了

8.2 C++11 noexcept

// C++11 簡潔版
size_type size() const noexcept;           // 承諾不拋異常
iterator begin() noexcept;                 // 承諾不拋異常

關(guān)鍵認知

  1. 編譯器不強制檢查——你用 noexcept 修飾了函數(shù),但里面調(diào)了 throw,編譯器照樣編譯通過(頂多給個警告)
  2. 運行時的處理——聲明了 noexcept 的函數(shù)如果真的拋了異常,程序會調(diào)用 std::terminate 終止
  3. 移動構(gòu)造/移動賦值盡量加 noexcept——這樣 STL 容器在做擴容等操作時才會優(yōu)先用移動而非拷貝

8.3 noexcept 運算符

#include <list>
double Divide(int a, int b) {
    if (b == 0) throw "Division by zero condition!";
    return (double)a / (double)b;
}
int main() {
    int i = 0;
    // noexcept(表達式) 在編譯期判斷表達式是否會拋異常
    cout << noexcept(Divide(1, 2)) << endl;  // 0 (false) —— 可能拋異常
    cout << noexcept(Divide(1, 0)) << endl;  // 0 (false) —— 可能拋異常
    cout << noexcept(++i)        << endl;  // 1 (true)  —— ++i 不拋異常
    list<int> lt;
    cout << noexcept(lt.begin()) << endl;    // 1 (true)  —— begin() 聲明了 noexcept
    return 0;
}

noexcept 運算符判斷的是表達式本身是否可能拋異常,不是判斷這次調(diào)用會不會拋。Divide(1, 0) 確實會拋異常,但 noexcept 只看函數(shù)的聲明,Divide 沒有聲明 noexcept,所以返回 false。

九、標(biāo)準(zhǔn)庫的異常體系

C++ 標(biāo)準(zhǔn)庫也有一套自己的異常繼承體系:

std::exception              ← 基類,virtual const char* what()
├── std::logic_error        ← 邏輯錯誤(可在編譯期檢測)
│   ├── std::invalid_argument
│   ├── std::out_of_range
│   └── std::length_error
├── std::runtime_error      ← 運行時錯誤
│   ├── std::overflow_error
│   ├── std::range_error
│   └── std::system_error
└── std::bad_alloc          ← new 失敗

日常寫程序時,主函數(shù)里 catch const std::exception& e,然后調(diào) e.what() 就能獲取錯誤信息。

int main() {
    try {
        // 你的程序
    }
    catch (const exception& e) {
        cout << "標(biāo)準(zhǔn)庫異常:" << e.what() << endl;
    }
    catch (...) {
        cout << "未知異常" << endl;
    }
    return 0;
}

你自己的異常體系也可以繼承 std::exception 并重寫 what(),這樣和標(biāo)準(zhǔn)庫風(fēng)格統(tǒng)一。

十、總結(jié)

知識點核心要點
基本語法throw 拋對象 → 沿調(diào)用鏈找 catch → 類型匹配就進去
棧展開逐層退出函數(shù),局部對象自動析構(gòu),直到找到匹配的 catch
匹配規(guī)則精確匹配 ,但允許派生類→基類、非const→const 等隱式轉(zhuǎn)換
繼承體系定義 Exception 基類+虛函數(shù) what(),各模塊繼承,外層只 catch 基類引用
重新拋出throw; 不加參數(shù),把當(dāng)前異常原樣再拋(不要用 throw e;
異常安全裸指針 + 異常 = 泄漏;用 RAII 或在 catch 中釋放后重新 throw
noexcept承諾不拋異常;聲明了但拋了會 terminate;移動構(gòu)造盡量加
標(biāo)準(zhǔn)庫std::exception 是標(biāo)準(zhǔn)異常的基類,what() 是虛函數(shù)

異常處理的完整思路:底層負責(zé)檢測和拋出(攜帶足夠信息),中層負責(zé)分類和重試,頂層負責(zé)兜底和通知用戶。配上一個設(shè)計良好的異常繼承體系,幾十萬行的項目也只需要一行 catch。

參考:C++ exception 標(biāo)準(zhǔn)庫參考

到此這篇關(guān)于C++異常處理完全指南的文章就介紹到這了,更多相關(guān)C++異常處理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 一文詳解Qt中線程的實際應(yīng)用

    一文詳解Qt中線程的實際應(yīng)用

    為了讓程序盡快響應(yīng)用戶操作,在開發(fā)應(yīng)用程序時經(jīng)常會使用到線程。這篇文章就來和大家介紹一下Qt中線程的實際應(yīng)用,感興趣的小伙伴可以了解一下
    2023-03-03
  • 在C++中高效使用和處理Json格式數(shù)據(jù)的示例代碼

    在C++中高效使用和處理Json格式數(shù)據(jù)的示例代碼

    最近的項目在用c處理后臺的數(shù)據(jù)時,因為好多外部接口都在使用Json格式作為返回的數(shù)據(jù)結(jié)構(gòu)和數(shù)據(jù)描述,如何在c中高效使用和處理Json格式的數(shù)據(jù)就成為了必須要解決的問題,需要的朋友可以參考下
    2023-11-11
  • C++無法從“const char[ ]”轉(zhuǎn)換為“char *”問題及解決

    C++無法從“const char[ ]”轉(zhuǎn)換為“char *”問題及解決

    這篇文章主要介紹了C++無法從“const char[ ]”轉(zhuǎn)換為“char *”問題及解決,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-04-04
  • C++類型轉(zhuǎn)換、IO流與特殊類的設(shè)計方法實例

    C++類型轉(zhuǎn)換、IO流與特殊類的設(shè)計方法實例

    在現(xiàn)代編程中,C++作為一種強大的面向?qū)ο缶幊陶Z言,其靈活性和高效性在開發(fā)中得到了廣泛應(yīng)用,類型轉(zhuǎn)換和輸入輸出流(IO流)是C++語言的兩個重要組成部分,這篇文章主要介紹了C++類型轉(zhuǎn)換、IO流與特殊類的設(shè)計方法的相關(guān)資料,需要的朋友可以參考下
    2025-12-12
  • C語言實現(xiàn)俄羅斯方塊源代碼

    C語言實現(xiàn)俄羅斯方塊源代碼

    這篇文章主要為大家詳細介紹了C語言實現(xiàn)俄羅斯方塊的源代碼,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-06-06
  • VS C++頭文件引用提示“未定義標(biāo)識符”的問題解決

    VS C++頭文件引用提示“未定義標(biāo)識符”的問題解決

    本文主要介紹了VS C++頭文件引用提示“未定義標(biāo)識符”的問題解決,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • C語言遞歸:漢諾塔問題分析

    C語言遞歸:漢諾塔問題分析

    這篇文章主要介紹了C語言遞歸:漢諾塔問題分析的相關(guān)資料,需要的朋友可以參考下
    2023-01-01
  • C語言猜兇手的代碼實現(xiàn)

    C語言猜兇手的代碼實現(xiàn)

    本文主要介紹了C語言猜兇手的代碼實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • C++實現(xiàn)LeetCode(768.可排序的最大塊數(shù)之二)

    C++實現(xiàn)LeetCode(768.可排序的最大塊數(shù)之二)

    這篇文章主要介紹了C++實現(xiàn)LeetCode(768.可排序的最大塊數(shù)之二),本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • Visual?Studio?Code?配置C、C++?文件debug調(diào)試環(huán)境的詳細過程

    Visual?Studio?Code?配置C、C++?文件debug調(diào)試環(huán)境的詳細過程

    這篇文章主要介紹了Visual?Studio?Code?配置C、C++?文件debug調(diào)試環(huán)境,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-02-02

最新評論

舒城县| 临桂县| 定南县| 大化| 镇康县| 大田县| 乌海市| 昌平区| 六枝特区| 忻州市| 板桥市| 金秀| 弥渡县| 家居| 万源市| 揭东县| 三明市| 体育| 平邑县| 修武县| 绥芬河市| 屏边| 大余县| 仪陇县| 枝江市| 建宁县| 贡觉县| 东明县| 磴口县| 海阳市| 青田县| 荣成市| 汝州市| 麟游县| 叙永县| 永清县| 盘山县| 定襄县| 安平县| 贺兰县| 邹平县|