向量vector

轉(zhuǎn)自:https://blog.csdn.net/weixin_42430671/article/details/88631535


一、向量的介紹

向量 vector 是一種對(duì)象實(shí)體, 能夠容納許多其他類(lèi)型相同的元素, 因此又被稱為容器。與string相同, vector 同屬于STL(Standard Template Library, 標(biāo)準(zhǔn)模板庫(kù))中的一種自定義的數(shù)據(jù)類(lèi)型, 可以廣義上認(rèn)為是數(shù)組的增強(qiáng)版;
??在使用它時(shí),需要包含vector頭文件敬拓,#include< vector >
??vector 容器與數(shù)組相比其優(yōu)點(diǎn)在于它能夠根據(jù)需要隨時(shí)自動(dòng)調(diào)整自身的大小以便容下所要放入的元素。此外, vector 也提供了許多的方法來(lái)對(duì)自身進(jìn)行操作镇草。

二、向量的聲明及初始化

vector 型變量的聲明以及初始化的形式也有許多, 常用的有以下幾種形式:

vector<int> a;                //聲明一個(gè)int型的向量a;
vector<int> a(10);            //聲明一個(gè)初始大小為10的向量a;
vector<int> a(10,1);          //聲明一個(gè)初始大小為10且初始值都未1的向量a;
vector<int> b(a);             //聲明并用向量a初始化b;
vector<int> b(a.begin(),a.begin()+3);     
                              //聲明并將向量a的第0個(gè)到第2個(gè)(共3個(gè))作為向量b的初始值

除此之外, 還可以直接使用數(shù)組來(lái)初始化向量:

int n[] = {1, 2, 3, 4, 5};
vector<int> a(n,n+5);              //將數(shù)組n的前5個(gè)元素作為向量a的初值
vector<int> a(&n[1],&n[4]);       //將n[1] - n[4]范圍內(nèi)的元素作為向量a的初值

三何暇、元素的輸入及訪問(wèn)

元素的輸入和訪問(wèn)可以像操作普通的數(shù)組那樣, 用cin>>進(jìn)行輸入, cout<<a[n]這樣進(jìn)行輸出:
示例:

1     #include<iostream>
2     #include<vector>
3 
4     using namespace std ;
5 
6     int main()
7     {
8         vector<int> a(10, 0) ;      //大小為10初值為0的向量a
9 
10         //對(duì)其中部分元素進(jìn)行輸入
11         cin >>a[2] ;
12         cin >>a[5] ;
13         cin >>a[6] ;
14 
15         //全部輸出
16         int i ;
17         for(i=0; i<a.size(); i++)
18             cout<<a[i]<<" " ;
19 
20         return 0 ;
21     }

在元素的輸出上, 還可以使用遍歷器(又稱迭代器)進(jìn)行輸出控制陶夜。
vector< int > b(a.begin(), a.begin()+3);這種聲明形式中, (a.begin()、a.begin()+3)表示向量起始元素位置到起始元素+3之間的元素位置裆站。 (a.begin() ,a.end())則表示起始元素和最后一個(gè)元素之外的元素位置条辟。
??向量元素的位置便成為遍歷器, 同時(shí), 向量元素的位置也是一種數(shù)據(jù)類(lèi)型, 在向量中遍歷器的類(lèi)型為: vector< int >::iterator黔夭。 遍歷器不但表示元素位置, 還可以再容器中前后移動(dòng)。
??在上例中講元素全部輸出部分的代碼就可以改寫(xiě)為:

//全部輸出
    vector<int>::iterator t ;
    for(t=a.begin(); t!=a.end(); t++)
        cout<<*t<<" " ;

*t 為指針的間接訪問(wèn)形式, 意思是訪問(wèn)t所指向的元素值羽嫡。

四本姥、向量的基本操作

  1. a.size() //獲取向量中的元素個(gè)數(shù);
  2. a.empty() //判斷向量是否為空杭棵;
  3. a.clear() //清空向量中的元素婚惫;
  4. a=b //將b向量復(fù)制到a向量中;
  5. 如a==b //a向量與b向量比較, 相等則返回1;
  6. 插入 - insert
    ①a.insert(a.begin(),1000); //將1000插入到向量a的起始位置前;
    ②a.insert(a.begin(),3,1000) ; //將1000分別插入到向量元素位置的0-2處魂爪;
    ③vector<int> a(5, 1) ;
    vector<int> b(10) ;
    b.insert(b.begin(),a.begin(),a.end()) ;
    //將a.begin(),a.end()之間的全部元素插入到b.begin()前
  7. 刪除 - erase
    ①b.erase(b.begin()) ; //將起始位置的元素刪除;
    ②b.erase(b.begin(),b.begin()+3); //將(b.begin(), b.begin()+3)之間的元素刪除;
  8. b.swap(a) ; //a向量與b向量進(jìn)行交換

五先舷、二維向量

與數(shù)組相同, 向量也可以增加維數(shù), 例如聲明一個(gè)m*n大小的二維向量方式可以像如下形式:
vector< vector<int> > b(10, vector<int>(5)); //創(chuàng)建一個(gè)10*5的int型二維向量
在這里, 實(shí)際上創(chuàng)建的是一個(gè)向量中元素為向量的向量。同樣可以根據(jù)一維向量的相關(guān)特性對(duì)二維向量進(jìn)行操作滓侍。
例:

 1     #include<iostream>
 2     #include<vector>
 3 
 4     using namespace std ;
 5 
 6     int main()
 7     {
 8         vector< vector<int> > b(10, vector<int>(5, 0)) ;
 9 
10         //對(duì)部分?jǐn)?shù)據(jù)進(jìn)行輸入
11         cin>>b[1][1] ;
12         cin>>b[2][2] ;
13         cin>>b[3][3];
14 
15         //全部輸出
16         int m, n ;
17         for(m=0; m<b.size(); m++)           //b.size()獲取行向量的大小
18         {
19             for(n=0; n<b[m].size(); n++)    //獲取向量中具體每個(gè)向量的大小
20                 cout<<b[m][n]<<" " ;
21             cout<<"\n" ;
22         }
23 
24         return 0;
25     }

同樣, 按照這樣的思路我們還可以創(chuàng)建更多維的向量, 不過(guò)維數(shù)太多會(huì)讓向量變得難以靈活控制, 三維以上的向量還需酌情使用蒋川。



1. 在C++中的詳細(xì)說(shuō)明

vector是C++標(biāo)準(zhǔn)模板庫(kù)中的部分內(nèi)容,它是一個(gè)多功能的撩笆,能夠操作多種數(shù)據(jù)結(jié)構(gòu)和算法的模板類(lèi)和函數(shù)庫(kù)捺球。
??vector之所以被認(rèn)為是一個(gè)容器,是因?yàn)樗軌蛳袢萜饕粯哟娣鸥鞣N類(lèi)型的對(duì)象夕冲,
??簡(jiǎn)單地說(shuō)氮兵,vector是一個(gè)能夠存放任意類(lèi)型的動(dòng)態(tài)數(shù)組,能夠增加和壓縮數(shù)據(jù)歹鱼。

2. 使用vector

必須在你的頭文件中包含下面的代碼:
#include
vector屬于std命名域的泣栈,因此需要通過(guò)命名限定,如下完成你的代碼:

 using std::vector;
 vector vInts; 

或者連在一起醉冤,使用全名:

std::vector vInts;

建議使用全局的命名域方式:

using namespace std;
  1. 初始化
vector                 // 創(chuàng)建一個(gè)空的vector秩霍。
vector c1(c2)          // 復(fù)制一個(gè)vector
vector c(n)            // 創(chuàng)建一個(gè)vector,含有n個(gè)數(shù)據(jù)蚁阳,數(shù)據(jù)均已缺省構(gòu)造產(chǎn)生 
vector c(n, elem)      // 創(chuàng)建一個(gè)含有n個(gè)elem拷貝的vector
vector c(beg,end)      // 創(chuàng)建一個(gè)含有n個(gè)elem拷貝的vector
  1. 析構(gòu)函數(shù)

5. 成員函數(shù)

c.assign(beg,end)c.assign(n,elem)
  將[beg; end)區(qū)間中的數(shù)據(jù)賦值給c铃绒。將n個(gè)elem的拷貝賦值給c。
??c.at(idx)
  傳回索引idx所指的數(shù)據(jù)螺捐,如果idx越界颠悬,拋出out_of_range。

   c.back()      // 傳回最后一個(gè)數(shù)據(jù)定血,不檢查這個(gè)數(shù)據(jù)是否存在赔癌。
   c.begin()     // 傳回迭代器中的第一個(gè)數(shù)據(jù)地址。
   c.capacity()  // 返回容器中數(shù)據(jù)個(gè)數(shù)澜沟。
   c.clear()     // 移除容器中所有數(shù)據(jù)灾票。
   c.empty()     // 判斷容器是否為空。
   c.end()       // 指向迭代器中末端元素的下一個(gè)茫虽,指向一個(gè)不存在元素刊苍。
   c.erase(pos)  // 刪除pos位置的數(shù)據(jù)既们,傳回下一個(gè)數(shù)據(jù)的位置。
   c.erase(beg,end)  //刪除[beg,end)區(qū)間的數(shù)據(jù)正什,傳回下一個(gè)數(shù)據(jù)的位置啥纸。
   c.front()     // 傳回第一個(gè)數(shù)據(jù)。
   
   get_allocator // 使用構(gòu)造函數(shù)返回一個(gè)拷貝婴氮。

   c.insert(pos,elem)    // 在pos位置插入一個(gè)elem拷貝斯棒,傳回新數(shù)據(jù)位置。
   c.insert(pos,n,elem)  // 在pos位置插入n個(gè)elem數(shù)據(jù)主经。無(wú)返回值荣暮。
   c.insert(pos,beg,end) // 在pos位置插入在[beg,end)區(qū)間的數(shù)據(jù)。無(wú)返回值旨怠。
  
   c.max_size()       // 返回容器中最大數(shù)據(jù)的數(shù)量渠驼。
   c.pop_back()       // 刪除最后一個(gè)數(shù)據(jù)。
   c.push_back(elem)  // 在尾部加入一個(gè)數(shù)據(jù)鉴腻。
   c.rbegin()         // 傳回一個(gè)逆向隊(duì)列的第一個(gè)數(shù)據(jù)。
   c.rend()           // 傳回一個(gè)逆向隊(duì)列的最后一個(gè)數(shù)據(jù)的下一個(gè)位置百揭。
   c.resize(num)      // 重新指定隊(duì)列的長(zhǎng)度爽哎。
   c.reserve()        // 保留適當(dāng)?shù)娜萘俊?   c.size()           // 返回容器中實(shí)際數(shù)據(jù)的個(gè)數(shù)。
   c1.swap(c2)
   swap(c1,c2)        // 將c1和c2元素互換器一。同上操作课锌。

   operator[]         // 返回容器中指定位置的一個(gè)引用享潜。

6. 用法示例:

6.1. 創(chuàng)建一個(gè)vector

vector容器提供了多種創(chuàng)建方法宝当,下面介紹幾種常用的睬罗。
創(chuàng)建一個(gè)Widget類(lèi)型的空的vector對(duì)象:
 vector vWidgets;
創(chuàng)建一個(gè)包含500個(gè)Widget類(lèi)型數(shù)據(jù)的vector:
vector vWidgets(500);
創(chuàng)建一個(gè)包含500個(gè)Widget類(lèi)型數(shù)據(jù)的vector酿矢,并且都初始化為0:
 vector vWidgets(500, Widget(0));
創(chuàng)建一個(gè)Widget的拷貝:
vector vWidgetsFromAnother(vWidgets);
向vector添加一個(gè)數(shù)據(jù):
 vector添加數(shù)據(jù)的缺省方法是push_back()姑荷。
?push_back()函數(shù)表示將數(shù)據(jù)添加到vector的尾部伟葫,并按需要來(lái)分配內(nèi)存鼓蜒。
?例如:向vector中添加10個(gè)數(shù)據(jù)家乘,需要如下編寫(xiě)代碼:

  for(int i= 0;i<10; i++) {
    vWidgets.push_back(Widget(i));
  }
6.2 獲取vector中指定位置的數(shù)據(jù)

vector里面的數(shù)據(jù)是動(dòng)態(tài)分配的方仿,使用push_back()的一系列分配空間常常決定于文件或一些數(shù)據(jù)源固棚。
如果想知道vector存放了多少數(shù)據(jù),可以使用empty()仙蚜。
獲取vector的大小此洲,可以使用size()。
例如委粉,如果想獲取一個(gè)vector v的大小呜师,但不知道它是否為空,或者已經(jīng)包含了數(shù)據(jù)贾节,如果為空想設(shè)置為-1汁汗,
你可以使用下面的代碼實(shí)現(xiàn):

  int nSize = v.empty() ? -1 : static_cast(v.size());

6.3 訪問(wèn)vector中的數(shù)據(jù)

使用兩種方法來(lái)訪問(wèn)vector趟紊。

1 vector::at()
2 vector::operator[]

operator[]主要是為了與C語(yǔ)言進(jìn)行兼容。它可以像C語(yǔ)言數(shù)組一樣操作碰酝。
但at()是我們的首選霎匈,因?yàn)閍t()進(jìn)行了邊界檢查,如果訪問(wèn)超過(guò)了vector的范圍送爸,將拋出一個(gè)例外铛嘱。
由于operator[]容易造成一些錯(cuò)誤,所有我們很少用它袭厂,下面進(jìn)行驗(yàn)證一下:
分析下面的代碼:

  vector v;
  v.reserve(10);

    for(int i=0; i<7; i++) {
    v.push_back(i);
  }

    try {int iVal1 = v[7];
    // not bounds checked - will not throw
    int iVal2 = v.at(7);
    // bounds checked - will throw if out of range
  } 

    catch(const exception& e) {
    cout << e.what();
  }

6.3 刪除vector中的數(shù)據(jù)

vector能夠非常容易地添加數(shù)據(jù)墨吓,也能很方便地取出數(shù)據(jù),
同樣vector提供了erase()纹磺,pop_back()帖烘,clear()來(lái)刪除數(shù)據(jù),
當(dāng)刪除數(shù)據(jù)時(shí)橄杨,應(yīng)該知道要?jiǎng)h除尾部的數(shù)據(jù)秘症,或者是刪除所有數(shù)據(jù),還是個(gè)別的數(shù)據(jù)式矫。

Remove_if()算法:如果要使用remove_if()乡摹,需要在頭文件中包含如下代碼:
#include
Remove_if()有三個(gè)參數(shù):
1 iterator _First:指向第一個(gè)數(shù)據(jù)的迭代指針〔勺  
2 iterator _Last:指向最后一個(gè)數(shù)據(jù)的迭代指針聪廉。
3 predicate _Pred:一個(gè)可以對(duì)迭代操作的條件函數(shù)。

6.4 條件函數(shù)

條件函數(shù)是一個(gè)按照用戶定義的條件返回是或否的結(jié)果故慈,是最基本的函數(shù)指針板熊,或是一個(gè)函數(shù)對(duì)象。
這個(gè)函數(shù)對(duì)象需要支持所有的函數(shù)調(diào)用操作察绷,重載operator()操作干签。
remove_if()是通過(guò)unary_function繼承下來(lái)的,允許傳遞數(shù)據(jù)作為條件克婶。
例如筒严,假如想從一個(gè)vector中刪除匹配的數(shù)據(jù),如果字串中包含了一個(gè)值情萤,從這個(gè)值開(kāi)始鸭蛙,從這個(gè)值結(jié)束。
首先應(yīng)該建立一個(gè)數(shù)據(jù)結(jié)構(gòu)來(lái)包含這些數(shù)據(jù)筋岛,類(lèi)似代碼如下:

#include 
enum findmodes {
  FM_INVALID = 0,
  FM_IS,
 FM_STARTSWITH,
 FM_ENDSWITH,
 FM_CONTAINS
};

typedef struct tagFindStr {
 UINT iMode;
 CString szMatchStr;
} FindStr;

typedef FindStr* LPFINDSTR;

然后處理?xiàng)l件判斷:
class FindMatchingString : public std::unary_function<cstring, bool=""> {
public:
 FindMatchingString(const LPFINDSTR lpFS) :
 m_lpFS(lpFS) {}
 bool operator()(CString& szStringToCompare) const {
  bool retVal = false;

    switch (m_lpFS->iMode) {
  case FM_IS: {
    retVal = (szStringToCompare == m_lpFDD->szMatchStr);
    break;
  }
  case FM_STARTSWITH: {
    retVal = (szStringToCompare.Left(m_lpFDD->szMatchStr.GetLength())
      == m_lpFDD->szWindowTitle);
    break;
  }
  case FM_ENDSWITH: {
    retVal = (szStringToCompare.Right(m_lpFDD->szMatchStr.GetLength())
      == m_lpFDD->szMatchStr);
  break;
  }
  case FM_CONTAINS: {
    retVal = (szStringToCompare.Find(m_lpFDD->szMatchStr) != -1);
    break;
  }
   }
   return retVal;
  }
private:
 LPFINDSTR m_lpFS;
};

通過(guò)這個(gè)操作你可以從vector中有效地刪除數(shù)據(jù):

FindStr fs;
fs.iMode = FM_CONTAINS;
fs.szMatchStr = szRemove;
vs.erase(std::remove_if(vs.begin(), vs.end(), FindMatchingString(&fs)), vs.end());

Remove(),remove_if()等所有的移出操作都是建立在一個(gè)迭代范圍上的娶视,不能操作容器中的數(shù)據(jù)。
所以在使用remove_if(),實(shí)際上操作的時(shí)容器里數(shù)據(jù)的上面的肪获。
看到remove_if()實(shí)際上是根據(jù)條件對(duì)迭代地址進(jìn)行了修改寝凌,在數(shù)據(jù)的后面存在一些殘余的數(shù)據(jù),
那些需要?jiǎng)h除的數(shù)據(jù)孝赫。剩下的數(shù)據(jù)的位置可能不是原來(lái)的數(shù)據(jù)较木,但他們是不知道的。
調(diào)用erase()來(lái)刪除那些殘余的數(shù)據(jù)青柄。
注意上面例子中通過(guò)erase()刪除remove_if()的結(jié)果和vs.enc()范圍的數(shù)據(jù)伐债。

7. 綜合例子:
//---------------------------------------------------------------------------
#include 
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------

#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
#include 
#include 
using namespace std;

struct STResult
{
    double Time;
    double Xp;
    double Yp;
    int id;
};

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
}

vector ResultVector;

void __fastcall test()
{
    //test
    //vector ResultVector;
    STResult stritem;
    stritem.Time = .1;
    stritem.Xp = .1;
    stritem.Yp = .1;
    stritem.id = 1;

    ResultVector.push_back( stritem );

}

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    test();
    assert(ResultVector[0].id == 1);
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市致开,隨后出現(xiàn)的幾起案子峰锁,更是在濱河造成了極大的恐慌,老刑警劉巖双戳,帶你破解...
    沈念sama閱讀 219,366評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件虹蒋,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡飒货,警方通過(guò)查閱死者的電腦和手機(jī)魄衅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)膏斤,“玉大人徐绑,你說(shuō)我怎么就攤上這事∧妫” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,689評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵毅访,是天一觀的道長(zhǎng)沮榜。 經(jīng)常有香客問(wèn)我,道長(zhǎng)喻粹,這世上最難降的妖魔是什么蟆融? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,925評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮守呜,結(jié)果婚禮上型酥,老公的妹妹穿的比我還像新娘。我一直安慰自己查乒,他們只是感情好弥喉,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,942評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著玛迄,像睡著了一般由境。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,727評(píng)論 1 305
  • 那天虏杰,我揣著相機(jī)與錄音讥蟆,去河邊找鬼。 笑死纺阔,一個(gè)胖子當(dāng)著我的面吹牛瘸彤,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播笛钝,決...
    沈念sama閱讀 40,447評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼质况,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了婆翔?” 一聲冷哼從身側(cè)響起拯杠,我...
    開(kāi)封第一講書(shū)人閱讀 39,349評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎啃奴,沒(méi)想到半個(gè)月后潭陪,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,820評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡最蕾,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,990評(píng)論 3 337
  • 正文 我和宋清朗相戀三年依溯,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片瘟则。...
    茶點(diǎn)故事閱讀 40,127評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡黎炉,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出醋拧,到底是詐尸還是另有隱情慷嗜,我是刑警寧澤,帶...
    沈念sama閱讀 35,812評(píng)論 5 346
  • 正文 年R本政府宣布丹壕,位于F島的核電站庆械,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏菌赖。R本人自食惡果不足惜缭乘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,471評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望琉用。 院中可真熱鬧堕绩,春花似錦、人聲如沸邑时。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,017評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)刁愿。三九已至绰寞,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背滤钱。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,142評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工觉壶, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人件缸。 一個(gè)月前我還...
    沈念sama閱讀 48,388評(píng)論 3 373
  • 正文 我出身青樓铜靶,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親他炊。 傳聞我的和親對(duì)象是個(gè)殘疾皇子争剿,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,066評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容