最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

C++ Primer 筆記-第12章 動態(tài)內(nèi)存

2023-01-07 14:32 作者:Code有毒  | 我要投稿
  1. 靜態(tài)內(nèi)存?用來保存局部?static?對象、類?static?數(shù)局成員以及定義在任何函數(shù)之外的變量。

  2. 棧內(nèi)存?用來保存定義在函數(shù)內(nèi)的非?static?對象。

  3. 分配在?靜態(tài)?或??內(nèi)存中的對象由編譯器自動創(chuàng)建和銷毀。

  4. 對于?棧對象,僅在其定義的程序塊運行時才存在。

  5. static?對象在使用之前分配,在程序結(jié)束時銷毀。

  6. 程序用?堆(heap)?來存儲?動態(tài)分配(dynamically allocate)?的對象(程序運行時分配的對象)。動態(tài)對象的生存期由程序來控制,當(dāng)動態(tài)對象不再使用時,我們的代碼必須顯式地銷毀它們。

  7. 雖然使用動態(tài)內(nèi)存有時是必要的,但是正確地管理動態(tài)內(nèi)存是非常棘手的。

12.1 動態(tài)內(nèi)存與智能指針

  1. new?在動態(tài)內(nèi)存中為對象分配空間并返回一個指向該對象的指針,我們可以選擇對對象進行初始化。

  2. delete?接受一個動態(tài)對象的指針,銷毀該對象,并釋放與之關(guān)聯(lián)的內(nèi)存。

  3. 忘記釋放內(nèi)存,會產(chǎn)生內(nèi)存泄漏。

  4. 在尚有指針引用內(nèi)存的情況下釋放了內(nèi)存,會產(chǎn)生引用非法內(nèi)存的指針。

  5. shared_ptr?允許多個指針指向同一個對象。

  6. unique_ptr?則 “獨占” 所指向的對象。

  7. weak_ptr?是一個伴隨類,一種弱引用,指向?shared_ptr?所管理的對象。

12.1.1?shared_ptr

  1. 默認初始化的智能指針中保存著一個空指針。

  2. p = q:p 和 q 都是?shared_ptr,此操作會遞減 p 指向?qū)ο蟮囊糜嫈?shù),遞增 q 原來指向?qū)ο蟮囊糜嫈?shù)。若 p 的引用計數(shù)變?yōu)?0,則將其管理的原內(nèi)存釋放。

  3. p.use_count()?返回與 p 共享對象的智能指針數(shù)量,可能很慢,主要用于調(diào)試。

  4. 到底是用一個計數(shù)器還是其他數(shù)據(jù)結(jié)構(gòu)來記錄有多少指針共享對象,完全由標(biāo)準庫的具體實現(xiàn)來決定。關(guān)鍵是智能指針能記錄有多少個?shared_ptr?指向相同的對象,并能在恰當(dāng)?shù)臅r候自動釋放對象。

  5. shared_ptr?在無用之后仍然保留的一種可能情況是:將?shared_ptr?存放在一個容器中,而后不再需要全部元素,而只使用其中一部分。(在此情況下,要記得用?erase?刪除不再需要的那些元素。)

  6. 程序使用動態(tài)內(nèi)存出于以下三種原因之一:
    (1)程序不知道自己需要使用多少對象
    (2)程序不知道所需對象的準確類型
    (3)程序需要在多個對象間共享數(shù)據(jù)

  7. 下面通過一個例子來詳細說明一下程序需要在多個對象間共享數(shù)據(jù)的情況:

// 數(shù)據(jù)不共享的情況:

vector<string> v1; ? ?// 空 vector

{ ? // 新作用域 ? ?

????vector<string> v2 = { "a", "an", "the" }; ? ?

????v1 = v2; ? ?// 從 v2 拷貝元素到 v1 中

} ? // v2 被銷毀,其中的元素也被銷毀 ? ?

????// v1 有三個元素,是原來 v2 中元素的拷貝


// 數(shù)據(jù)共享的情況:

// 假定我們希望定義一個名為 StrBlob 的類,保存一組元素

// 與容器不同,我們希望 StrBlob 對象的不同拷貝之間共享相同的元素

StrBlob b1; ? ?// 空 StrBlob


{ ? // 新作用域

? ?StrBlob b2 = { "a", "an", "the" };

? ?b1 = b2; ? ?// b2 和 b1 共享相同的元素

} ? // b2 被銷毀了,但是 b2 中的元素不能銷毀

? ??// b1 指向最初的由 b2 創(chuàng)建的元素

  1. 接下來我們定義?StrBlob?類(使用?vector?來保存元素,并將?vector?保存在動態(tài)內(nèi)存中):

// StrBlob.h

class StrBlob{

public:

? ?StrBlob();

? ?StrBlob(std::initializer_list<std::string> il);

private:

? ?std::shared_ptr<str::vector<string>> data;

}

// StrBlob.cpp

StrBlob::StrBlob() : data(make_shared<vector<string>>()) {}

StrBlob::StrBlob(initializer_list<string> il) :

? ? ? ? ? ? ? ?data(make_shared<vector<string>>(il)) {}

  1. 當(dāng)我們拷貝、賦值或銷毀一個?StrBlob?對象時,它的?Shared_ptr?成員也會被拷貝、賦值或銷毀。

  2. 拷貝一個?shared_ptr?會遞增其引用計數(shù);將一個?shared_ptr?賦予另一個?shared_ptr?會遞增賦值號右側(cè)的?shared_ptr?的引用計數(shù),而遞減左側(cè)?shared_ptr?的引用計數(shù)。

  3. 如果一個?shared_ptr?的引用計數(shù)變?yōu)?0 ,它所指向的對象會被自動銷毀。因此,對于由?StrBlob?構(gòu)造函數(shù)分配的?vector,當(dāng)最后一個指向它的?StrBlob?對象被銷毀時,它會隨之被自動銷毀。

12.1.2 直接管理內(nèi)存

  1. C++ 定義了兩個運算符來分配和釋放動態(tài)內(nèi)存:運算符?new?分配內(nèi)存,delete?釋放?new?分配的內(nèi)存。

  2. 相對于智能指針,使用這兩個運算符管理內(nèi)存非常容易出錯,在學(xué)習(xí)第13章前,除非使用智能指針來管理內(nèi)存,否則不要分配動態(tài)內(nèi)存。

  3. 在自由空間(堆)分配的內(nèi)存是?無名?的,因此?new?無法為其分配的對象命名,而是返回一個指向該對象的指針:

    int* pi = new int; ? ? ? ? ?// pi指向一個動態(tài)分配的、未初始化的無名對象

  4. 默認情況下,動態(tài)分配的對象是?默認初始化?的,這意味著?內(nèi)置類型?或?組合類型的對象?的值將是?未定義?的,而?類類型對象?將用?默認構(gòu)造函數(shù)?進行初始化。

  5. 也可以使用?直接初始化傳統(tǒng)的構(gòu)造方式(使用圓括號)、列表初始化) 和?值初始化(使用空括號)?來動態(tài)分配對象。

// 默認初始化

string* ps1 = new string; ? ? ? ? ? ?// 默認初始化為空string

int* pi1 = new int; ? ? ? ? ? ? ? ? ?// 默認初始化,*pi1的值未定義

// 傳統(tǒng)構(gòu)造方式

int *pi2 = new int(1024); ? ? ? ? ? ?// pi2指向的對象值為1024

string* ps2 = new string(10, '9'); ? // *ps2為“9999999999”

vector<int>* pv = new vector<int>{0, 1, 2, 3}; ?// vector有4個元素,值依次從0到3

// 值初始化

string* ps3 = new string(); ? ? ? ? ?// 值初始化為空string

int* pi3 = new int(); ? ? ? ? ? ? ? ?// 值初始化為0

  1. 出于于變量初始化相同的原因,對動態(tài)分配的對象進行初始化通常是個好主意。

  2. 對于一個定義了默認構(gòu)造函數(shù)的類類型,其?const?動態(tài)對象可以隱式初始化,而其他類型的對象就必須顯示初始化。

const string* pcs = new const string; ? // 隱式初始化

const int* pci = new const int(1024); ? // 顯示初始化

  1. 可以使用?定位 new (placement new)?來阻止動態(tài)對象分配時因內(nèi)存耗盡而拋出的異常。

int* p1 = new int; ? ? ? ? ? ? ?// 如果分配失敗,會拋出 std::bad_alloc

// 向new傳遞一個標(biāo)準庫定義的nothrow對象

int* p2 = new (nothrow) int; ? ?// 如果分配失敗,返回一個空指針

  1. delete?表達式執(zhí)行兩個動作:銷毀給定的指針指向的對象;釋放對應(yīng)的內(nèi)存。

  2. 傳遞給?delete?的指針必須指向?動態(tài)分配的內(nèi)存,或者?空指針。釋放一塊并非?new?分配的內(nèi)存,或者將相同的指針值釋放多次,其行為是未定義的。

  3. 通常情況下,編譯器不能分辨一個指針指向的是靜態(tài)還是動態(tài)分配的對象。編譯器也不能分辨一個指針?biāo)赶虻膬?nèi)存是否以及被釋放了。

  4. 由內(nèi)置指針(而不是智能指針)管理的動態(tài)內(nèi)存在被顯示釋放前一直都會存在。

  5. 使用?new?和?delete?管理動態(tài)內(nèi)存有三個常見的問題:
    (1)忘記?delete?內(nèi)存;
    (2)使用已經(jīng)釋放掉的對象;
    (3)同一塊內(nèi)存被釋放兩次。

  6. 堅持只使用?智能指針,就可以避免所有這些問題。對于一塊內(nèi)存,只有在沒有任何智能指針指向它的情況下,智能指針才會自動釋放它。

  7. 在?delete?之后,指針就變成了?空懸指針(dangling pointer)(指向一塊曾經(jīng)保存數(shù)據(jù)對象但現(xiàn)在已經(jīng)無效的內(nèi)存的指針),在?delete?之后將?nullptr?賦予指針,可以清楚的指出指針不指向任何對象。

  8. 當(dāng)有多個指針指向相同的內(nèi)存時,在?delete?內(nèi)存之后重置指針的辦法只對這個指針有效,對其他任何仍指向(已釋放的)內(nèi)存的指針是沒有用的。

int* p(new int(1024)); ?// p指向動態(tài)內(nèi)存

auto q = p; ? ? ? ? ? ? // p和q指向同一塊內(nèi)存

delete p; ? ? ? ? ? ? ? // p和q均變?yōu)闊o效

p = nullptr; ? ? ? ? ? ?// 此時p不再綁定到任何對象

// 此時重置p對q沒有任何作用,q仍然指向原來那塊(已經(jīng)被釋放的)內(nèi)存地址

// 在實際系統(tǒng)中,查找指向相同內(nèi)存的所有指針是異常困難的!

12.1.3?shared_ptr?和?new?結(jié)合使用

  1. 接受指針參數(shù)的智能指針構(gòu)造函數(shù)是?explicit?的。因此,我們不能將一個內(nèi)置指針隱式轉(zhuǎn)換為一個智能指針,必須使用?直接初始化形式?來初始化一個智能指針。:

shared_ptr<int> p1 = new int(1024); // 錯誤:必須使用直接初始化形式

shared_ptr<int> p2(new int(1024)); ?// 正確:使用了直接初始化形式

  1. 一個返回?shared_ptr?的函數(shù)不能在其返回語句中隱式轉(zhuǎn)換一個普通指針:

shared_ptr<int> clone(int p){

? ?return new int(p); ? ? ? ? ? ? ? ? ????????????// 錯誤

? ?return shared_ptr<int>(new int(p)); // 正確

}

  1. 一般情況下,一個用來初始化智能指針的普通指針必須指向動態(tài)內(nèi)存,因此智能指針默認使用?delete?釋放它所關(guān)聯(lián)的對象。 但是也可以將智能指針綁定到一個指向其他類型的資源的指針上,只是此時需要提供自己的釋放操作來替代?delete。

// 如果p是唯一指向其對象的shared_ptr,reset會釋放此對象。

p.reset();

// 若傳遞了可選的參數(shù)內(nèi)置指針q,會令p指向q,否則會將p置為空。

p.reset(q);

//若還傳遞了參數(shù)d,將會調(diào)用d而不是delete來釋放q

p.reset(q, d);

  1. 不要混合使用普通指針和智能指針,使用一個內(nèi)置指針來訪問一個智能指針?biāo)撠?zé)的對象是很危險的,因為我們無法知道對象何時會被銷毀:

// ptr是傳值方式傳遞,因此拷貝時會遞增其引用次數(shù)。

void process(shared_ptr<int> ptr){

? ? // 使用ptr

} ? // ptr離開作用域,ptr會被銷毀。由于ptr銷毀了,引用次數(shù)會遞減


// process正確的使用方法:

shared_ptr<int> p(new int(42)); // 此時引用計數(shù)為1

process(p); ? ? // 拷貝p會遞增其引用次數(shù),此時在process中引用計數(shù)值為2

int i = *p;? ? ? ? ?// 離開了process作用域,引用計數(shù)值為1?


// process錯誤的使用方法:

int *x(new int(1024)); ?// 危險:x是普通指針,不是智能指針

process(x);? ? ? ? ? ? ? ?? // 錯誤:不能將int* 轉(zhuǎn)換為shared_ptr<int>

process(shared_ptr<int>(x)); // 合法,但是由于傳參時使用的是一個臨時變量,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 臨時變量在傳遞完之后會被銷毀,所以傳完參

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??// 之后的process里的ptr引用計數(shù)為1

int j = *x; // 未定義:離開了process作用域,引用計數(shù)值為0,此時x為一個懸空指針

  1. get?用來將指針的訪問權(quán)限傳遞給代碼,只有在確定代碼不會?delete?指針的情況下,才能使用?get。特別是,永遠不要用?get?初始化另一個智能指針或者為另一個智能指針賦值。

shared_ptr<int> p(new int(42)); // 引用計數(shù)為1

// 新程序塊

{

? ?// 兩個獨立的shared_ptr指向相同的內(nèi)存

? ? ? ?shared_ptr<int> q(p.get()); ? // 錯誤:將get用來初始化指針指針

} ? // 程序塊結(jié)束,q被銷毀,它指向的內(nèi)存被釋放

int foo = *p; ? // 未定義:p指向的內(nèi)存已經(jīng)被釋放了

12.1.4 智能指針和異常

  1. 那些分配了資源,而又?沒有定義析構(gòu)函數(shù)?來釋放這些資源的類,可能會遇到與使用動態(tài)內(nèi)存相同的錯誤——程序員非常容易忘記釋放資源。與管理動態(tài)內(nèi)存類似,我們通??梢允褂弥悄苤羔榿砉芾聿痪哂辛己枚x的析構(gòu)函數(shù)的類:

class destination;

class connection; ? // 假定connection沒有析構(gòu)函數(shù)

connection connect(destination* d) {}

void disconnect(connection c) {}

void f(destination& d){

? ?connection c = connect(&d);

? ?// ...

? ?// 如果我們在f退出前忘記調(diào)用disconnect,就無法關(guān)閉c了

}


// 使用智能指針管理對象的生命周期

// 定義刪除器

void end_connection(connection* p) { disconnect(*p); }

void f(destination& d){?

? ?connection c = connect(&d);

? ?shared_ptr<connection> p(&c, end_connection);

? ?// ...

? ?// 當(dāng)f退出時(即便是由于異常而退出),connection會被正確關(guān)閉

}

  1. 智能指針陷阱:

    (1)不使用相同的內(nèi)置指針值初始化(或?reset?)多個智能指針。
    (2)不?delete?get()?返回的指針。
    (3)不使用?get()?初始化或?reset?另一個智能指針。
    (4)如果你使用?get()?返回的指針,記住當(dāng)最后一個對應(yīng)的智能指針銷毀后,你的指針就變?yōu)闊o效了。
    (5)如果你使用智能指針管理的資源不是?new?分配的內(nèi)存,記住傳遞給它一個刪除器。

12.1.5?unique_ptr

  1. 一個?unique_ptr?“擁有” 它所指向的對象。某個時刻只能有一個?unique_ptr?指向一個給定對象,當(dāng)?unique_ptr?被銷毀時,它所指向的對象也被銷毀。

  2. 定義一個?unique_ptr?時,需要將其綁定到一個?new?返回的指針上。初始化?unique_ptr?必須采用直接初始化形式。

  3. unique_ptr?不支持普通的拷貝或賦值操作。

  4. 不能拷貝?unique_ptr?的規(guī)則有一個例外:我們可以拷貝或賦值一個將要被銷毀的?unique_ptr。常見的例子是從函數(shù)返回一個?unique_ptr

unique_ptr<int> clone(int p) {?

? ?return unique_ptr<int>(new int(p));

}

unique_ptr<int> clone(int p) {?

? ?unique_ptr<int> ret(new int(p));

? ?return ret;

}

  1. 向?unique_ptr?傳遞刪除器:

// 將之前的例子中的shared_ptr換成unique_ptr

void f(destination& d){

? ?connection c = connect(&d);

? ?// 使用decltype來指明函數(shù)指針類型

? ?// 必須加一個*來指出我們正在使用該類型的指針

? ?unique_ptr<connection, decltype(end_connection)*>

? ? ? ?p(&c, end_connection);

}

12.1.6?weak_ptr

  1. weak_ptr是一種不控制所指向?qū)ο笊嫫诘闹悄苤羔?,它指向由一個?shared_ptr?管理的對象。

  2. 將一個?weak_ptr?綁定到一個?shared_ptr?不會改變?shared_ptr?的引用計數(shù)。一旦最后一個指向?qū)ο蟮?shared_ptr?被銷毀,對象就會被釋放。即使有?weak_ptr?指向?qū)ο?,對象也還是會被釋放。因此,weak_ptr?的名字抓住了這種智能指針 “弱” 共享對象的特點。

  3. 由于對象可能不存在,我們不能使用?weak_ptr?直接訪問對象,而必須調(diào)用?lock。檢查對象是否存在,如果存在,lock?返回一個指向共享對象的?shared_ptr,否則返回一個空?shared_ptr

auto p = make_shared<int>(42);

weak_ptr<int> wp(p); ? ?// wp弱共享p;p的引用計數(shù)未改變

// 如果np不為空則條件成立

if(shared_ptr<int> np = wp.lock()) {

? ?// 在if中,np與p共享對象

}

12.2 動態(tài)數(shù)組

  1. 大多數(shù)應(yīng)用應(yīng)該使用?標(biāo)準庫容器?而不是?動態(tài)分配的數(shù)組。使用容器更為簡單、更不容易出現(xiàn)內(nèi)存管理錯誤并且可能有更好的性能。

  2. 使用容器的類可以使用默認版本的拷貝、賦值和析構(gòu)操作。分配動態(tài)數(shù)組的類則必須定義自己版本的操作,在拷貝、賦值以及銷毀對象時管理所關(guān)聯(lián)的內(nèi)存。

12.2.1?new?和數(shù)組

  1. 為了讓?new?分配一個對象數(shù)組,我們要在類型名之后跟一對方括號,指明要分配的對象的數(shù)目。

int* p1 = new int[42]; ?// p1指向第一個int

//也可以使用一個表達數(shù)組類型的類型別名來分配一個數(shù)組

typedef int arrT[42]; ? // arrT表示42個int的數(shù)組類型

int* p = new arrT; ? ? ?// 分配一個42個int的數(shù)組,p指向第一個int

  1. 通常稱?new T[]?分配的內(nèi)存為 “動態(tài)數(shù)組”,但是這種叫法有些誤導(dǎo)。實際上我們得到的是一個指向第一個元素的數(shù)組元素類型的指針。

  2. 不能對動態(tài)數(shù)組調(diào)用?begin?、end?和范圍?for?循環(huán)操作。

  3. 可以對數(shù)組中的元素進行值初始化,方法是加()或{}列表。

int* pia = new int[3]; ? ? ? ? ? ? ?// 3個未初始化的int

int* pia2 = new int[3](); ? ? ? ? ? // 3個值初始化為0的int

int* pia3 = new int[3]{0, 1, 2}; ? ?// 跟列表相同的int

int* pia4 = new int[3]{0, 1, 2, 3}; // 列表數(shù)目超出,拋出bad_array_new_length異常

// 雖然可以用空括號對數(shù)組中元素的進行值初始化

// 但是不能在括號中給出初始化器

// 這意味著不能用auto分配數(shù)組

int obj = 1;auto p = new auto[3](obj);

  1. int* p = new int[0];:當(dāng)用?new?分配一個大小為0的數(shù)組時,new?返回一個合法的非空指針。此指針保證與?new?返回的其他任何指針都不相同。我們可以像使用尾后迭代器一樣使此指針。但是此指針?不能解引用。

  2. delete [] p;?釋放一個指向數(shù)組的指針時,方括號是必須的。

  3. 在?delete?一個數(shù)組時忘記了方括號,或者在?delete?一個單一對象的指針時使用了方括號,編譯器很可能?不會給出警告。我們的程序可能在執(zhí)行過程中在沒有任何警告的情況下行為異常(行為是未定義的)。

  4. 標(biāo)準庫提供一個可以管理?new?分配到數(shù)組的?unique_ptr?版本,但是不能使用點和箭頭成員運算符操縱。

unique_ptr<int[]> up(new int[10]);

for(size_t i = 0; i != 10; ++i)

? ?up[i] = i; ?// 可以使用下標(biāo)運算符來訪問數(shù)組中的元素。

up.release(); ? // 自動用delete[]銷毀其指針

  1. shared_ptr?不直接支持管理動態(tài)數(shù)組。如果希望使用,必須提供自己定義的刪除器。否則將會使用默認的?delete?而不是?delete[]?銷毀對象。

shared_ptr<int> sp(new int[10, [](int* p) { delete[] p; }]);

// shared_ptr 未定義下標(biāo)運算符,并且不支持指針的算數(shù)運算

for(size_t i = 0; i != 10; ++i)

? ?????*(sp.get() + i) = i; ? ?// 必須用get獲取內(nèi)置指針才能訪問元素

sp.reset(); // shared_ptr沒有release()

12.2.2?allocator?類

  1. 當(dāng)分配單個對象時,通常希望將內(nèi)存分配和對象初始化組合在一起(對應(yīng)操作是?new?和?delete)。當(dāng)分配一大塊內(nèi)存時,我們通常計劃在一塊內(nèi)存上按需構(gòu)造對象,此時我們希望內(nèi)存分配和對象構(gòu)造分離

  2. 標(biāo)準庫?allocator?類幫助我們將內(nèi)存分配和對象構(gòu)造分離開來。它提供一種類型感知的內(nèi)存分配方式,它分配的內(nèi)存是原始的、未構(gòu)造的。

int n = 3;

allocator<string> alloc; ? ? ? // 可以分配string的allocator對象

auto const p = alloc.allocate(n);// 分配n個未初始化的string


auto q = p; ? ? ? ? ? ? ? ? ? ?// q指向最后構(gòu)造的元素之后的位置

alloc.construct(q++); ? ? ? ? ?// *q為空字符串

alloc.construct(q++, 10, 'c'); // *q為cccccccccc

alloc.construct(q++, "hi"); ? ?// *q為hi!


// 在還未構(gòu)造對象的情況下使用原視內(nèi)存是錯誤的:

cout << *p << endl; ? ? ? ? ? ?// 正確:使用string的輸出運算符

cout << *q << endl; ? ? ? ? ? ?// 錯誤:q指向未構(gòu)造的內(nèi)存!


// 用完對象后,必須銷毀每個構(gòu)造的元素

while(q != p)

? ?alloc.destroy(--q); ? ? ? ?// 釋放我們真正構(gòu)造的string


// 釋放內(nèi)存

alloc.deallocate(p, n);

  1. 標(biāo)準庫還為?allocator?類定義了兩個伴隨算法,可以在未初始化內(nèi)存中創(chuàng)建對象:

vector<int> vi{0, 1, 2, 3};


// 分配一塊比vector中元素所占用空間大一倍的動態(tài)內(nèi)存,

allocator<string> alloc;

auto p = alloc.allocate(vi.size() * 2);


// 然后將原vector中的元素拷貝到前一半空間,

// copy有兩種寫法:

// q 指向最后一個構(gòu)造的元素之后的位置。

auto q = uninitialized_copy(vi.begin(), vi.end(), p);

auto q = uninitialized_copy_n(vi.begin(), vi.size(), p);


// 對后一半的空間用一個給定值進行填充,

// fill也有兩種寫法:

uninitialized_fill(q, q + n, 42);uninitialized_fill_n(q, vi.size(), 42);



C++ Primer 筆記-第12章 動態(tài)內(nèi)存的評論 (共 條)

分享到微博請遵守國家法律
镇安县| 望都县| 四平市| 宁强县| 汉川市| 阜城县| 北海市| 偃师市| 福海县| 板桥市| 宣化县| 洛扎县| 荥阳市| 锦屏县| 高平市| 新龙县| 柳江县| 京山县| 麻城市| 栾城县| 南通市| 买车| 无极县| 昌黎县| 原平市| 定襄县| 长沙市| 江华| 永登县| 乌海市| 正定县| 涪陵区| 定西市| 米林县| 吉木萨尔县| 上虞市| 武平县| 宜宾市| 岱山县| 阿城市| 凭祥市|