亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C++ > 正文

c++常見面試題

2019-11-06 06:40:02
字體:
來源:轉載
供稿:網友

1,關于動態申請內存

答:內存分配方式三種:

(1)從靜態存儲區域分配:內存在程序編譯的時候就已經分配好,這塊內存在程序的整個運行期間都存在。

全局變量,static變量。

(2)在棧上創建:在執行函數時,函數內局部變量的存儲單元都可以在棧上創建,

函數執行結束時這些存儲單元自動被釋放。

棧內存分配運算內置于處理器的指令集中,效率很高,但是分配的內存容量有限。

(3)用malloc或new申請內存之后,應該立即檢查指針值是否為NULL.防止使用指針值為NULL的內存,

不要忘記為數組和動態內存賦初值。防止將未被初始化的內存作為右值使用。避免數組或指針的下標越界,

特別要當心發生“多1”或者“少1”操作。動態內存的申請與釋放必須配對,防止內存泄漏。

用free或delete釋放了內存之后,立即將指針設置為NULL,防止產生“野指針”。從堆上分配,亦稱動態內存分配。

程序在運行的時候用malloc或new申請任意多少的內存,程序員自己負責在何時用free或delete釋放內存。

動態內存的生存期由程序員決定,使用非常靈活。(int*pArray;   intMyArray[6];   pArray = &MyArray[0];)

如果在申請動態內存時找不到足夠大的內存塊,malloc和new將返回NULL指針,

判斷指針是否為NULL,如果是則馬上用return語句終止本函數,

或者馬上用exit(1)終止整個程序的運行,為new和malloc設置異常處理函數。

 

2,C++指針攻破

答案:指針是一個變量,專門存放內存地址,特點是能訪問所指向的內存

 

指針本身占據了4個字節的長度

int **ptr; //指針的類型是 int **

int (*ptr)[3]; //指針的類型是int(*)[3] 

int *(*ptr)[4]; //指針的類型是 int*(*)[4] 

 ptr++:指針ptr的值加上了sizeof(int)

ptr+=5:將指針ptr的值加上5*sizeof(int)

 

指針的賦值:

把一個變量的地址賦予指向相同數據類型的指針變量( inta;   int*ip  ip=&a;)

把一個指針變量的值賦予指向相同類型變量的另一個指針變量(inta;  int *pa=&a; int *pb;   pb=pa; )

把數組的首地址賦予指向數組的指針變量(int a[5],*pa; pa=a;  也可寫為:pa=&a[0];)

 

如果給指針加1或減1 ,實際上是加上或減去指針所指向的數據類型大小。

當給指針加上一個整數值或減去一個整數值時,表達式返回一個新地址。

相同類型的兩個指針可以相減,減后返回的整數代表兩個地址間該類型的實例個數。

 

int ** cc=new (int*)[10];聲明一個10個元素的數組,數組每個元素都是一個int *指針,

每個元素還可以單獨申請空間,因為cc的類型是int*型的指針,所以你要在堆里申請的話就要用int*來申請;

   int ** a= newint * [2];     //申請兩個int * 型的空間

   a[0] = newint[4];        ////為a的第一個元素申請了4個int 型空間,a[0] 指向了此空間的首地址處

   a[1] = newint[3];        //為a的第二個元素又申請了3個int 型空間,a[1]指向了此空間首地址處

 

指針數組初始化賦值:

一維指針開辟空間:char *str;int*arr;   scanf(“%d”,&N);

str=(char*)malloc(sizeof(char)*N);

arr=(int*)malloc(sizeof(int)*N);

二維指針開辟空間:int**arr,     i;         scanf(“%d%d”,&row,&col);

arr=(int**)malloc(sizeof(int)*row);

for(i=0;i<row;i++)

  arr[i]=(int*)malloc(sizeof(int)*col);

 

結構體指針數組,例如typedefstruct{   charx;   int  y;}Quan,*QQuan;

定義一個結構體指針數組如:QQuan a[MAX] 

for(i=0;i<MAX;i++)

{

   a[i]=(QQuan)malloc(sizeof(Quan));

   memset(a[i],0,sizeof(Quan));

}

指針數組賦值

 floata[]={100,200,300,400,500};

float *p[5]={&a[0],&a[1],&a[2],&a[3],&a[4]};

 

 

char *units[1000];

charget_unit[250];                                                                           

for(int i=0;i<get_unit_num;i++){units[i]=(char*) malloc(60*sizeof(char*)); 

scanf(“%s”,get_unit);  strcpy(units[i],get_unit);}

 

 

3,復雜指針解析:

(1)int (*func)(int *p);

(*func)()是一個函數,func是一個指向這類函數的指針,就是一個函數指針,這類函數具有int*類型的形參,返回值類型是int。

(2)int (*func)(int *p, int (*f)(int*));

func是一個指向函數的指針,這類函數具有int *和int (*)(int*)這樣的形參。形參int(*f)(int*),f也是一個函數指針

(3)int (*func[5])(int *p);

func數組的元素是函數類型的指針,它所指向的函數具有int*類型的形參,返回值類型為int。

(4)int (*(*func)[5])(int *p);

func是一個指向數組的指針,這個數組的元素是函數指針,這些指針指向具有int*形參,返回值為int類型的函數。

(5)int (*(*func)(int *p))[5];

func是一個函數指針,這類函數具有int*類型的形參,返回值是指向數組的指針,所指向的數組的元素是具有5個int元素的數組。

注意:

需要聲明一個復雜指針時,如果把整個聲明寫成上面所示的形式,對程序可讀性是一大損害。

應該用typedef來對聲明逐層,分解,增強可讀性,例如對于聲明:int (*(*func)(int*p))[5];

這樣分解:typedef  int(*PARA)[5];   typedef PARA (*func)(int *);

 

例如:int (*(*func)[5][6])[7][8];

  func是一個指向數組的指針,這類數組的元素是一個具有5X6個int元素的二維數組,而這個二維數組的元素又是一個二維數組。

  typedef int (*PARA)[7][8];

  typedef PARA (*func)[5][6];

例如:int (*(*(*func)(int *))[5])(int *);

  func是一個函數指針,這類函數的返回值是一個指向數組的指針,

所指向數組的元素也是函數指針,指向的函數具有int*形參,返回值為int。

  typedef int (*PARA1)(int*);

  typedef PARA1 (*PARA2)[5];

  typedef PARA2 (*func)(int*);

 

 

4,函數指針詳解

答:

函數指針是指向一個函數入口的指針

一個函數指針只能指向一種類型的函數,即具有相同的返回值和相同的參數的函數。

函數指針數組定義:void(*fun[3])(void*); 相應指向類A的成員函數的指針:void (A::*pmf)(char *, const char *);

指向外部函數的指針:void (*pf)(char *, const char *); voidstrcpy(char * dest, const char * source); pf=strcpy;

 

 

5,野指針

答:“野指針”是很危險的,if語句對它不起作用?!耙爸羔槨钡某梢蛑饕袃煞N:

(1)指針變量沒有被初始化。指針變量在創建的同時應當被初始化,要么將指針設置為NULL,要么讓它指向合法的內存。

char *p =NULL;     char *str = (char *) malloc(100);

(2)指針p被free或者delete之后,沒有置為NULL

(3)指針操作超越了變量的作用范圍。所指向的內存值對象生命期已經被銷毀

 

6,引用和指針有什么區別?

答:引用必須初始化,指針則不必;引用初始化以后不能改變,指針可以改變其指向的對象;

不存在指向空值的引用,但存在指向控制的指針;

引用是某個對象的別名,主要用來描述函數和參數和返回值。而指針與一般的變量是一樣的,會在內存中開辟一塊內存。

如果函數的參數或返回值是類的對象的話,采用引用可以提高程序的效率。

 

7,C++中的Const用法

答:char * constp;    //指針不可改,也就說指針只能指向一個地址,不能更改為其他地址,修飾指針本身

char const * p;  // 所指內容不可改,也就是說*p是常量字符串,修飾指針所指向的變量

const char * const p 和 char const * const p; //內容和指針都不能改

 

const修飾函數參數是它最廣泛的一種用途,它表示函數體中不能修改參數的值,

傳遞過來的參數在函數內不可以改變,參數指針所指內容為常量不可變,參數指針本身為常量不可變

在引用或者指針參數的時候使用const限制是有意義的,而對于值傳遞的參數使用const則沒有意義

 

const修飾類對象表示該對象為常量對象,其中的任何成員都不能被修改。

const修飾的對象,該對象的任何非const成員函數都不能被調用,因為任何非const成員函數會有修改成員變量的企圖。

const修飾類的成員變量,表示成員常量,不能被修改,同時它只能在初始化列表中賦值。staticconst 的成員需在聲明的地方直接初始。

const修飾類的成員函數,則該成員函數不能修改類中任何非const成員。一般寫在函數的最后來修飾。

在函數實現部分也要帶const關鍵字.

對于const類對象/指針/引用,只能調用類的const成員函數,因此,const修飾成員函數的最重要作用就是限制對于const對象的使用

 

使用const的一些建議:在參數中使用const應該使用引用或指針,而不是一般的對象實例

const在成員函數中的三種用法(參數、返回值、函數)要很好的使用;

const在成員函數中的三種用法(參數、返回值、函數)要很好的使用;

不要輕易的將函數的返回值類型定為const;除了重載操作符外一般不要將返回值類型定為對某個對象的const引用;

 

8,const常量與define宏定義的區別

答:(1) 編譯器處理方式不同。define宏是在預處理階段展開,生命周期止于編譯期。

只是一個常數、一個命令中的參數,沒有實際的存在。

#define常量存在于程序的代碼段。const常量是編譯運行階段使用,const常量存在于程序的數據段.

 

(2)類型和安全檢查不同。define宏沒有類型,不做任何類型檢查,僅僅是展開。

const常量有具體的類型,在編譯階段會執行類型檢查。

(3) 存儲方式不同。define宏僅僅是展開,有多少地方使用,就展開多少次,不會分配內存。

const常量會在內存中分配(可以是堆中也可以是棧中)

 

9,解釋堆和棧的區別

答:1、棧區(stack)—由編譯器自動分配釋放,存放函數的參數值,局部變量的值等。其操作方式類似于數據結構中的棧。

由系統自動分配。聲明在函數中一個局部變量 int b; 系統自動在棧中為b開辟空間 。

只要棧的剩余空間大于所申請空間,系統將為程序提供內存,否則將報異常提示棧溢出。

在Windows下,棧是向低地址擴展的數據結構,是一塊連續的內存的區域,棧的大小是2M。

如果申請的空間超過棧的剩余空間時,將提示overflow。

棧由系統自動分配,速度較快。但程序員是無法控制的。

函數調用時,第一個進棧的是主函數中后的下一條指令,的地址,然后是函數的各個參數。

在大多數的C編譯器中,參數是由右往左入棧的,然后是函數中的局部變量。注意靜態變量是不入棧的。

 

堆區(heap) — 一般由程序員分配釋放,若程序員不釋放,程序結束時可能由OS回收 。

注意它與數據結構中的堆是兩回事,分配方式倒是類似于鏈表,需要程序員自己申請,并指明大小,在c中malloc函數

在C++中用new運算符。首先應該知道操作系統有一個記錄空閑內存地址的鏈表,當系統收到程序的申請時,

另外,由于找到的堆結點的大小不一定正好等于申請的大小,系統會自動的將多余的那部分重新放入空閑鏈表中。

堆是向高地址擴展的數據結構,是不連續的內存區域。而鏈表的遍歷方向是由低地址向高地址。

堆的大小受限于計算機系統中有效的虛擬內存。

堆是由new分配的內存,一般速度比較慢,而且容易產生內存碎片,不過用起來最方便

一般是在堆的頭部用一個字節存放堆的大小。

 

10,論述含參數的宏和函數的優缺點

(1)函數調用時,先求出實參表達式的值,然后代入形參。而使用帶參的宏只是進行簡單的字符替換

(2)函數調用是在程序運行時處理的,分配臨時的內存單元;而宏展開是在編譯時進行的,在展開時不進行

內存分配,不進行值得傳遞處理,沒有“返回值”概念

(3)對函數中的形參和實參都要定義類型,類型要求一致,如不一致則進行類型轉換。而宏不存在類型問題

(4)調用函數只可得到一個返回值,而用宏則可以設法得到幾個結果

(5)實用宏次數多時,宏展開后源程序變長,沒展開一次源程序增長,函數調用則不會

(6)宏替換不占用運行時間,只占編譯時間,而函數調用占用運行時間

 

11,C++的空類,默認產生哪些類成員函數?

答:class Empty

{

 public:

Empty();                          //缺省構造函數

Empty(const Empty&);          //拷貝構造函數

~Empty();                         //虛構函數

Empty& Operator(constEmpty&)    //賦值運算符

Empty&operator&();              //取址運算符

const Empty* operator&()const;   // 取址運算符 const

}

 

12,談談類和結構體的區別

答:結構體在默認情況下的成員都是public的,而類在默認情況下的成員是PRivate的。結構體和類都必須使用new創建,

struct保證成員按照聲明順序在內存在存儲,而類不保證。

 

13,C++四種強制類型轉換

答:(1)const_cast

字面上理解就是去const屬性,去掉類型的const或volatile屬性。

struct SA{  intk};  const SAra;   

ra.k =10;   //直接修改const類型,編譯錯誤  SA& rb = const_cast<SA&>(ra);  rb.k = 10; //可以修改

 

(2)static_cast

主要用于基本類型之間和具有繼承關系的類型之間的轉換。用于指針類型的轉換沒有太大的意義

static_cast是無條件和靜態類型轉換,可用于基類和子類的轉換,基本類型轉換,把空指針轉換為目標類型的空指針,

把任何類型的表達式轉換成void類型,static_cast不能進行無關類型(如非基類和子類)指針之間的轉換。

inta;    double d =static_cast<double>(a);  //基本類型轉換

int &pn =&a;    void *p =static_cast<void*>(pn);  //任意類型轉換為void

 

(3)dynamic_cast

 

你可以用它把一個指向基類的指針或引用對象轉換成繼承類的對象

動態類型轉換,運行時類型安全檢查(轉換失敗返回NULL)

基類必須有虛函數,保持多態特性才能用dynamic_cast

只能在繼承類對象的指針之間或引用之間進行類型轉換

class BaseClass{public:  intm_iNum;  virtual void foo(){};};

class DerivedClass:BaseClass{public: char*szName[100];  void bar(){};};

BaseClass* pb = new DerivedClass();

 

DerivedClass *p2 =dynamic_cast<DerivedClass *>(pb);

BaseClass* pParent =dynamic_cast<BaseClass*>(p2);

//子類->父類,動態類型轉換,正確

 

(4)reinterpreter_cast

轉換的類型必須是一個指針、引用、算術類型、函數指針或者成員指針。

主要是將一個類型的指針,轉換為另一個類型的指針

不同類型的指針類型轉換用reinterpreter_cast

最普通的用途就是在函數指針類型之間進行轉換

int DoSomething(){return 0;};

typedef void(*FuncPtr)(){};

FuncPtr funcPtrArray[10];

funcPtrArray[0] =reinterpreter_cast<FuncPtr>(&DoSomething);

 

14,C++函數中值的傳遞方式有哪幾種?

答:函數的三種傳遞方式為:值傳遞、指針傳遞和引用傳遞。

 

15,將“引用”作為函數參數有哪些特點

答:(1)傳遞引用給函數與傳遞指針的效果是一樣的,這時,被調函數的形參就成為原來主調函數的實參變量或者

對象的一個別名來使用,所以在被調函數中形參的操作就是對相應的目標對象的操作

(2)使用引用傳遞函數的參數,在內存中并沒有產生實參的副本,它是直接對實參操作,當參數數據較大時,引用

傳遞參數的效率和所占空間都好

(3)如果使用指針要分配內存單元,需要重復使用“*指針變量名”形式進行計算,容易出錯且閱讀性較差。

 

16,簡單敘述面向對象的三個基本特征

答:封裝性

把客觀事物封裝成抽象的類,對自身的數據和方法進行(public,private,protected)

繼承性

繼承概念的實現方式有三類:實現繼承、接口繼承和可視繼承。

實現繼承是指使用基類的屬性和方法而無需額外編碼的能力;

接口繼承是指僅使用屬性和方法的名稱、但是子類必須提供實現的能力;

可視繼承是指子窗體(類)使用基窗體(類)的外觀和實現代碼的能力。

抽象類僅定義將由子類創建的一般屬性和方法,創建抽象類時,請使用關鍵字 Interface 而不是Class

多態性

多態性(polymorphisn)是允許你將父對象設置成為和一個或更多的他的子對象相等的技術,賦值之后,

父對象就可以根據當前賦值給它的子對象的特性以不同的方式運作。允許將子類類型的指針賦值給父類類型的指針。

實現多態,有二種方式,覆蓋(子類重新定義父類的虛函數),重載(允許存在多個同名函數,參數個數,類型不同)。

 

17,類成員函數的overload, override 和 隱藏的區別

答:(1)成員函數被重載的特征:相同的類范圍,函數名字相同,參數不同,virtual 關鍵字可有可無。

(2)覆蓋指派生類的函數覆蓋基類函數,特征是分別位于基類和派生類,函數名字相同,參數相同,基類函數必須有virtual關鍵字

(3)隱藏是指派生類的函數屏蔽了與其同名的基類函數。1,派生類的函數與基類的函數同名,但是參數不同,

不論有無virtual關鍵字,基類的函數將被隱藏2,派生類的函數與基類的函數同名,并且參數也相同,

但是基類函數沒有virtual 關鍵字。此時,基類的函數被隱藏

3種情況怎么執行:重載:看參數;隱藏:用什么就調用什么;覆蓋:調用派生類 。

 

18,什么是預編譯,何時需要預編譯

答:就是指程序執行前的一些預處理工作,主要指#表示的.

需要預編譯的情況:總是使用不經常改動的大型代碼體。所有模塊都使用一組標準的包含文件和相同的編譯選項。

 

19,memset ,memcpy 和strcpy 的根本區別?

答:memset用來對一段內存空間全部設置為某個字符,一般用在對定義的字符串進行初始化為’‘或”;

它對較大的結構體或數組進行清零操作的一種最快方法。

chartemp[30];    memset(temp,’/0’,sizeof(temp));

chartemp[30]只是分配了一定的內存空間給該字符數組,但并未初始化該內存空間,即數組。所以,需要使用memset()來進行初始化。

memcpy用來做內存拷貝,你可以拿它拷貝任何數據類型的對象,可以指定拷貝的數據長度;

strcpy就只能拷貝字符串了,它遇到’/0’就結束拷貝;例:chara[100],b[50];strcpy(a,b);

 

20,多態類中的虛函數表是Compile-Time,還是Run-Time時建立的?

答:虛擬函數表是在編譯期就建立了,各個虛擬函數這時被組織成了一個虛擬函數的入口地址的數組.

而對象的隱藏成員–虛擬函數表指針是在運行期也就是構造函數被調用時進行初始化的,這是實現多態的關鍵.

 

21,Template有什么特點?什么時候用?

答: Template可以獨立于任何特定的類型編寫代碼,是泛型編程的基礎.

當我們編寫的類和函數能夠多態的用于跨越編譯時不相關的類型時,用Template.

模板主要用于STL中的容器,算法,迭代器等以及模板元編程.

C++的template是實現在庫設計和嵌入式設計中的關鍵,

能實現抽象和效率的結合;同時template還能有效地防止代碼膨脹

C++中為什么用模板類?

1)可用來創建動態增長和減小的數據結構

2)它是類型無關的,因此具有很高的可復用性

3)它在編譯時而不是運行時檢查數據類型,保證了類型安全

4)它是平臺無關的,可移植性

5)可用于基本數據類型

 

22,進程和線程的差別?

答:線程是指進程內的一個執行單元,也是進程內的可調度實體.區別:

(1)調度:線程作為調度和分配的基本單位,進程作為擁有資源的基本單位

(2)并發性:不僅進程之間可以并發執行,同一個進程的多個線程之間也可并發執行

(3)擁有資源:進程是擁有資源的一個獨立單位,線程不擁有系統資源,但可以訪問隸屬于進程的資源.

(4)系統開銷:創建撤消進程,系統都要為之分配和回收資源,系統的開銷明顯大于創建撤消線程

多進程與多線程,兩者都可以提高程序的并發度,提高程序運行效率和響應時間。

 

23,請說出static關鍵字盡可能多的作用

答:(1)函數體內作用范圍為該函數體,該變量內存只被分配一次,具有記憶能力

(2)在模塊內的static全局變量可以被模塊內所有函數訪問,但不能被模塊外其它函數訪問;

(3)在模塊內的static函數只可被這一模塊內的其它函數調用,這個函數的使用范圍被限制在聲明它的模塊內;

(4)在類中的static成員變量屬于整個類所擁有,對類的所有對象只有一份拷貝;

(5)在類中的static成員函數屬于整個類所擁有,這個函數不接收this指針,因而只能訪問類的static成員變量。

 

24,頭文件的作用是什么?

答:一,通過頭文件來調用庫功能。在很多場合,源代碼不便(或不準)向用戶公布,只要向用戶提供頭文件

和二進制的庫即可。用戶只需要按照頭文件中的接口聲明來調用庫功能,而不必關心接口怎么實現的。

編譯器會從庫中提取相應的代碼。

二,頭文件能加強類型安全檢查。如果某個接口被實現或被使用時,其方式與頭文件中的聲明不一致,

編譯器就會指出錯誤,這一簡單的規則能大大減輕程序員調試、改錯的負擔。

 

25,在C++程序中調用C編譯后的函數,為什么要加extern C的聲明?

答:因為C++支持函數重載,而C不支持函數重載,函數被C++編譯后在庫中的名字與C語言的不同。

假設某個函數的原型為:void foo(int x, inty);該函數被C編譯器編譯后在庫中的名字為_foo,

而C++編譯器則產生像_foo_int_int之類的名字。 C++提供externC來解決名字匹配問題

 

26,C++中哪些函數不能被聲明為虛函數?

答:普通函數(非成員函數),構造函數,內聯成員函數、靜態成員函數、友元函數。

(1)虛函數用于基類和派生類,普通函數所以不能

(2)構造函數不能是因為虛函數采用的是虛調用的方法,允許在只知道部分信息的情況的工作機制,

特別允許調用只知道接口而不知道對象的準確類型的方法,但是調用構造函數即使要創建一個對象,

那勢必要知道對象的準確類型。

(3)內聯成員函數的實質是在調用的地方直接將代碼擴展開

(4)繼承時,靜態成員函數是不能被繼承的,它只屬于一個類,因為也不存在動態聯編等

(5)友元函數不是類的成員函數,因此也不能被繼承

 

27, 數組int c[3][3]; 為什么c,*c的值相等,(c+1),(*c+1)的值不等,c,*c,**c,代表什么意思?

答:c是第一個元素的地址,*c是第一行元素的首地址,其實第一行元素的地址就是第一個元素的地址,

**c是提領第一個元素。 為什么c,*c的值相等?

c: 數組名;是一個二維指針,它的值就是數組的首地址,也即第一行元素的首地址(等于 *c),

也等于第一行第一個元素的地址( &c[0][0]);可以說成是二維數組的行指針。

*c: 第一行元素的首地址;是一個一維指針,可以說成是二維數組的列指針。

**c:二維數組中的第一個元素的值;即:c[0][0]

所以:c 和 *c的值是相等的,但他們兩者不能相互賦值,(類型不同)

(c + 1) :c是行指針,(c + 1)是在c的基礎上加上二維數組一行的地址長度,

即從&c[0][0]變到了&c[1][0];

(*c + 1):*c是列指針,(*c +1)是在*c的基礎上加上二數組一個元素的所占的長度,

&c[0][0]變到了&c[0][1],從而(c + 1)和(*c +1)的值就不相等了。

 

28,定義  int**pa[4][3],則變量pa占有的內存空間是多少?

答:int **p,在32位機器上 sizeof(p) = 4;

總共占有4*3*sizeof(p) = 48.

 

29,拷貝構造函數相關問題,深拷貝,淺拷貝,臨時對象等

答:在C++中,三種對象需要拷貝的情況:一個對象以值傳遞的方式傳入函數體,

 一個對象以值傳遞的方式從函數返回,一個對象需要通過另外一個對象進行初始化。

執行先父類后子類的構造,對類中每一個數據成員遞歸地執行成員拷的動作.

深拷貝:如果一個類擁有資源,深拷貝意味著拷貝了資源和指針

淺拷貝:如果對象存在資源,而淺拷貝只是拷貝了指針,沒有拷貝資源,

這樣使得兩個指針指向同一份資源,造成對同一份析構兩次,程序崩潰。

臨時對象的開銷比局部對象小些。

 

臨時對象:輔助一個表達式的計算 a + b + c,或者間接構造的實參,函數返回非引用的時候,

都可能產生臨時對象,臨時對象生命周期,是單個語句,是右值。

臨時對象的開銷比局部對象小些。

 

30,指針和引用有什么分別;

答:引用必須初始化,即引用到一個有效的對象;而指針在定義的時候不必初始化,

可以在定義后面的任何地方重新賦值。

引用初始化后不能改變,指針可以改變所指的對象

不存在指向NULL的引用,但存在指向NULL的指針

引用的創建和銷毀并不會調用類的拷貝構造函數

語言層面,引用的用法和對象一樣;在二進制層面,引用一般都是通過指針來實現的,

只不過編譯器幫我們完成了轉換.引用既具有指針的效率,又具有變量使用的方便性和直觀性.

 

31,寫一個”標準”宏MIN,這個宏輸入兩個參數并返回較小的一個

答:面試者注意謹慎將宏定義中的“參數”和整個宏用括號括起來

#define     MIN(A,B)    ((A) <= (B)? (A):(B))

 

32,用一個宏定義FIND求一個結構體struc中某個變量相對struc的偏移量

答:  #define FIND(struc,e)  (size_t)&(((struc*)0)->e )

解析:其中(struc*)0表示將常量0轉化為struc*類型指針所指向的地址。

&( ((struc*)0)->e)表示取結構體指針(struc*)0的成員e的地址,因為該結構體的首地址為0,

所以其實就是得到了成員e距離結構體首地址的偏移量,(size_t)是一種數據類型,為了便于不同系統之間的移植,

最好定義為一種無符號型數據,一般為unsigned int

 

33,解析sizeof 以及 結構體的對齊問題

答:(1)sizeof(type),用于數據類型;

sizeof(var_name)或sizeof var_name用于變量 

sizeof操作符不能用于函數類型,不完全類型或位字段。

不完全類型指具有未知存儲大小的數據類型,如未知存儲大小的數組類型、未知內容的結構或聯合類型、void類型等。

如int max(), char char_v [MAX]且MAX未知  , void類型

那么sizeof(max),sizeof(char_v),sizeof(void)都是錯誤的

 

當sizeof的參數為數組或者指針時

int  a[50];    //sizeof(a)=4*50=200;  求數組所占的空間大小

int  *a=new  int[50];//  sizeof(a)=4;  a為一個指針,sizeof(a)是求指針  

當sizeof的參數為結構或類時候

結構或者類中的靜態成員不對結構或者類的大小產生影響,因為靜態變量的存儲位置 。

與結構或者類的實例地址無關。沒有成員變量的結構或類的大小為1,

因為必須保證結構或類的每一 實例在內存中都有唯一的地址

 

(2)classMyStruct{   doubleddal;    chardda;    inttype;}

在VC中測試上面結構的大小時,你會發現sizeof(MyStruct)為16。

其實,這是VC對變量存儲的一個特殊處理。為了提高CPU的存儲速度,VC對一些變量的起始

地址做了“對齊”處理。在默認情況下,VC規定各成員變量存放的起始地址相對于結構的

始地址偏移量必須為該變量的類型占用字節數的倍數,如Char偏移量為sizeof(char)即1的倍數

 

先為第一個成員dda1分配空間,其起始地址跟結構的起始地址相同,偏移量0剛好為sizeof(double)的倍數,

該成員變量占用sizeof(double)=8個字節;接下來為第二個成員dda分配空間,這時

下一個可以分配的地址對于結構的起始地址的偏移量為8,是sizeof(char)的倍數,占sizeof(char)=1字節

為第三個成員type分配空間,這時下一個可以分配的地址對于結構的起始地址的偏移量為9

,不是sizeof(int)=4的倍數,為了滿足對齊方式對偏移量的約束問題,VC自動填充3個字節

這時下一個可以分配的地址對于結構的起始地址的偏移量是12,剛好是sizeof(int)=4的倍數,

所以把type存放在偏移量為12的地方,占用sizeof(int)=4個字節??偟恼加玫目臻g大

小為:8+1+3+4=16,剛好為結構的字節邊界數(即結構中占用最大空間的類型所占用的字節

數sizeof(double)=8)的倍數,所以沒有空缺的字節需要填充。

 

34,在main函數執行之前,還會執行什么代碼和工作

答:運行全局構造器,全局對象的構造函數會在main函數之前執行

設置棧指針,初始化static靜態和global全局變量,即數據段的內容

將未初始化部分的賦初值:數值型short,int,long等為0,bool為FALSE,指針為NULL等

將main函數的參數,argc,argv等傳遞給main函數

 

35,如何判斷一段程序是由C 編譯程序還是由C++ 編譯程序編譯的?

答:C++ 編譯時定義了 __cplusplus

C 編譯時定義了 _STDC_

 

36,分別寫出BOOL,int, float, 指針類型的變量 a 與 “零值”的比較語句

答:

  BOOL:if(!a)  or   if(a)

    int : if( 0== a)

  float : const EXPRESSION EXP =0.000001;

  if(a < EXP&& a > -EXP)

 pointer:    if(a != NULL) or  if(a == NULL)

 

37,已知String類定義如下,嘗試寫出類的成員函數實現

class{

public:

String(const char*str =NULL);            //通用構造函數

String(const String&another);            //拷貝構造函數

~String();                                //析構函數

String& operator = = (constString& rhs);  //賦值函數

private:

char*m_data;                             //用于保存字符串

};

 

答:

String::String(const char*str)

{

    if(str == NULL)

    {

           m_data = new char[1];

           m_data[0] = ‘/0’;

    }

    else

    {

           m_data = new char[strlen(str)+1];

           strcpy(m_data,str);        

    }

  

String::String(const String&another)

{

    m_data = new char[strlen(another.m_data)+1];

    strcpy(m_data, another.m_data); 

                        

String::String& operator = = (constString& rhs)

{

    if(this ==&rhs)

    return&this;

   delete[]  m_data;

    m_data = newchar(strlen(rhs.m_data)+1);  //刪除原來的數據,新開一塊內存

   strcpy(m_data,rhs.m_data); 

    return *this;

}

~String()

{

   delete[]  m_data;

}

 

38,論述C++類繼承的優缺點

答:一,優點:類繼承是在編譯時刻靜態定義的,可以直接使用,類繼承可以較方便的改變從父類繼承的實現

二,缺點:1,因為繼承在編譯時刻就定義了,所以無法在運行時刻改變從父類繼承的實現

2,父類通常至少定義了子類的部分行為,父類的任何改變都可能影響到子類的行為

3,如果繼承下來的實現不適合解決新的問題,則父類必須重寫或被其他更適合的類替換

這種依賴關系先限制了靈活性并最終限制了復用性

 

39,運算符重載的三種方式和不允許重載的5個運算符

答:運算符重載意義是為了對用戶自定義數據的操作和內定義的數據類型的操作形式一致

(1)普通函數,友元函數,類成員函數

(2).*(成員指針訪問運算符)   

     ::(域運算符) 

     sizeof長度運算符   

   ?:條件運算符   

    .(成員訪問運算符)

40,友元關系有什么特性?

答:單向的,非傳遞的, 不能繼承的.

 

41,理解析構函數和虛函數的用法和作用?

答:析構函數也是特殊的類成員函數,它沒有返回類型,沒有參數,不能隨意調用,也沒有重載。

在類對象生命期結束的時候,由系統自動調用釋放在構造函數中分配的資源。

析構函數一般在對象撤消前做收尾工作,比如回收內存等工作。

 

虛函數的功能是使子類可以用同名的函數對父類函數進行重載,并且在調用時自動調用子類重載函

數,在基類中通過使用關鍵字virtual來聲明一個函數為虛函數,該函數的功能可能在將來的派生類

中定義或者在基類的基礎上擴展,系統只能在運行階段才能動態的決定調用哪一個函數,動態的多態性,

如果是純虛函數,則純粹是為了在子類重載時有個統一的命名而已。

 

42,關鍵字volatile有什么含意?并給出三個不同的例子

答:一個定義為volatile的變量是說這變量可能會被意想不到地改變,編譯器就不會去假設這個變量的值了。

精確地說就是,優化器在用到這個變量時必須每次都小心地重新讀取這個變量的值

而不是使用保存在寄存器里的備份。下面是volatile變量的幾個例子:

1) 并行設備的硬件寄存器(如:狀態寄存器)

2) 一個中斷服務子程序中會訪問到的非自動變量(Non-automaticvariables)

3) 多線程應用中被幾個任務共享的變量

 

深究:一個參數既可以是const還可以是volatile,一個例子是只讀的狀態寄存器,

它是volatile因為它可能被意想不到地改變,是const因為程序不應該試圖去修改它。

一個指針可以是volatile,一個例子是當一個中服務子程序修該一個指向一個buffer的指針時。

 

43,動態連接庫的兩種方式?

答:調用一個DLL中的函數有兩種方法:

1.載入時動態鏈接(load-time dynamiclinking),模塊非常明確調用某個導出函數

,使得他們就像本地函數一樣。這需要鏈接時鏈接那些函數所在DLL的導入庫,導入庫向

系統提供了載入DLL時所需的信息及DLL函數定位。

2.運行時動態鏈接(run-time dynamiclinking),運行時可以通過LoadLibrary或Loa

dLibraryEx函數載入DLL。DLL載入后,模塊可以通過調用GetProcAddress獲取DLL函數的

出口地址,然后就可以通過返回的函數指針調用DLL函數了。如此即可避免導入庫文件了。

 

44,C和C++有什么不同?

答:從機制上:c是面向過程的。c++是面向對象的,提供了類。c++編寫面向對象的程序比c容易。

從適用的方向:c適合要求代碼體積小的,效率高的場合,如嵌入式;c++適合更上層的,復雜的; 

llinux核心大部分是c寫的,因為它是系統軟件,效率要求極高。

C語言是結構化編程語言,C++是面向對象編程語言

C++側重于對象而不是過程,側重于類的設計而不是邏輯的設計。

 

45,C++編譯器自動為類產生的四個確缺省函數是什么?

答:默認構造函數,拷貝構造函數,析構函數,賦值函數

 

46,簡單描述Windows內存管理的方法。

答:程序運行時需要從內存中讀出這段程序的代碼,代碼的位置必須在物理內存中才能被運行,

由于現在的操作系統中有非常多的程序運行著,內存中不能夠完全放下,所以引出了虛擬內存的概念。

把哪些不常用的程序片斷就放入虛擬內存,當需要用到它的時候在load入主存(物理內存)中。

內存管理也計算程序片段在主存中的物理位置,以便CPU調度。

 

內存管理有塊式管理,頁式管理,段式和段頁式管理。現在常用段頁式管理

塊式管理:把主存分為一大塊、一大塊的,當所需的程序片斷不在主存時就分配一塊主存空間,

把程 序片斷load入主存,就算所需的程序片度只有幾個字節也只能把這一塊分配給它。

這樣會造成很大的浪費,平均浪費了50%的內存空間,但時易于管理。

頁式管理:把主存分為一頁一頁的,每一頁的空間要比一塊一塊的空間小很多,顯然這種方法

的空間利用率要比塊式管理高很多

段式管理:把主存分為一段一段的,每一段的空間又要比一頁一頁的空間小很多,

這種方法在空間利用率上又比頁式管理高很多,但是也有另外一個缺點。一個程序片斷可能會被分為幾十段,

這樣很多時間就會被浪費在計算每一段的物理地址上,計算機最耗時間的大家都知道是I/O吧

段頁式管理:結合了段式管理和頁式管理的優點。把主存分為若干頁,每一頁又分為若干段,好處就很明顯

 

47,Linux有內核級線程嗎?

答:線程通常被定義為一個進程中代碼的不同執行路線。從實現方式上劃分,線程有兩種類型:

“用戶級線程”和“內核級線程”。用戶線程指不需要內核支持而在用戶程序中實現的線程,其不依賴于操作系統核心,

應用進程利用線程庫提供創建、同步、調度,和管理線程的函數來控制用戶線程。內核級線程需要內核的參與,

由內核完成線程的調度。其依賴于操作系統核心,由內核的內部需求進行創建和撤銷。

 

用戶線程不需要額外的內核開支,并且用戶態線程的實現方式可以被定制或修改以適應特殊應用的要求,

但是當一個線程因 I/O 而處于等待狀態時,整個進程就會被調度程序切換為等待狀態,其他線程得不

到運行的機會;而內核線程則沒有這個個限制,有利于發揮多處理器的并發優勢,但卻占用了更多的系統開支。

 

48,main 主函數執行完畢后,是否可能會再執行一段代碼,給出說明?

答:可以,可以用_onexit 注冊一個函數,它會在main 之后執行int fn1(void),fn2(void), fn3(void), fn4 (void)

 

49, i++ 相比 ++i 哪個更高效?為什么?

答:

(1)++i 比 i++效率高。

(2)i++要多調用一次類的構造和析夠函數

 

50,windows平臺下網絡編程有哪幾種網絡編程模型?

答:有阻塞,select,基于窗體的事件模型,事件模型,重疊模型,完成端口模型。

除了阻塞模型外,其他都是非阻塞模型,其中效率最高的是完成端口模型,尤其在windows下服務器最合適了。

做客戶端一般用事件模型了,select在window和類unix都可以使用。

 

51,什么是函數模板

答:函數模板技術定義了參數化的非成員函數,使得程序能夠使用不同的參數類型調用相同的函數,而至于是何種類型,

則是由編譯器確定從模板中生成相應類型的代碼。編譯器確定了模板函數的實際類型參數,稱之為模板的實例化。

template<classT>定義模板標識

T Add(T a, Tb)        //函數模板

{

   T result = a +b;

   return a +b;   //將兩個參數使用“+”運算符進行運算,這兩個參數并不知道是何種類型

}

該函數與一般函數的不同之處在于沒有明確指出使用何種數據類型和返回值又是哪一種類型

如何在程序中調用該函數

#include<iostream> //包含標準輸入輸出頭文件

#include<string>  //C++中的字符串處理頭文件

using namespace std;

template<class T>

T Add(T a, Tb)        //函數模板

{

   T result = a +b;

   return a +b;   //將兩個參數使用“+”運算符進行運算,這兩個參數并不知道是何種類型

}

int main(int argc, char* argv[])

{

   cout<<”2+3=”<<Add(2,3)<<endl; //輸出整形的+運算結果

  cout<<”sdf+123=”<<Add(string(“sdf”),string(“123”))<<endl;

  return 0;

}

 

52,什么是類模板

答:描述了能夠管理其他數據類型的通用數據類型,通常用于建立包含其他類型的容器類

對于這些容器,無論是哪一種數據類型,其操作方式是一樣的,但是針對具體的類型又是專用的,

template<class T>

class TemplateSample

{

   private:

   T&emtity;           //使用參數類型成員

    public:

  void F(T&arg);       //使用參數類型定義成員函數

}

該示例定義了一個類模板,類模板中的模板形參T需要用戶在使用的時候進行定義

TemplateSample<int>demo;  //針對該模板使用int類型

demo.F(123);  //調用類模板中的成員函數

template<class T1, class T2, intnum>     //定義多個模板參數,且其中一個直接使用int類型

該示例的前兩個參數可以是任何類型,但是第三個參數一定是int類型

TemplateSample<int , char,12>demo;     //使用非類類型的模板

#include<iostream>

template<class T, class T2, intnum>

class CSampleTemplate

{

   private:

   T t1;

   T2 t2;

  public:

  CSampleTemplate(T arg1, T2arg2)        //構造函數中使用模板參數

  {

     t1 = arg1 + num;

     t2 = arg2 + num;

  }

  void Write()

 {

 std::cout<<”t1:”<<t1<<”t2”<<t2<<endl;

 }

 

CSampleTemplate ()

{}

}

int main(int argc, char* argv[])

{

   CSampleTemplate<int, int,3>temp(1,2);

   temp.Write();

    return0;

}

53,什么是容器

答:STL是一個標準的C++庫,容器只是其中一個重要的組成部分,有順序容器和關聯容器

1)順序容器,指的是一組具有相同類型T的對象,以嚴格的線性形式組織在一起

包括vector<T>,  deque<T>,   list<T>

2)關聯容器,提供一個key實現對對象的隨機訪問,其特點是key是有序的元素是按照預定義的鍵順序插入的i

set<Key>,集合,  支持唯一鍵值,提供對鍵本身的快速檢索,例如set<long>:{學號}

set<Key>,多重集合,支持可重復鍵值,提供對鍵本身的快速檢索,例如multiset<string>:{姓名}

map<Key,T>,支持唯一Key類型的鍵值,提供對另一個基于鍵的類型的快速檢索,例如map<long,string>:{學號,姓名}

multimap<Key, T>,多重映射,支持可重復Key值,提供對另外一個基于鍵類型T的快速檢索,例如map<string,string>:{姓名,地址}

 

54,介紹關聯容器

答:#include<vector>    //包含頭文件

usingstd::vector          //使用命名限定

vector<int>vInts;

創建一個Widget類型為空的vector對象

vector<Widget>vWidgets;                   //空的vector對象

vector<Widget>vWidgets(500);            //包含500個對象的vector

vector<Widget>vWidgets(500,Widget(0));      //包含500個對象的vector,并且初始化為0

vector<Widget>vWidgetFromAnother(vWeigets);       //利用現有的vector創建一個拷貝

向vector中添加一個數據,默認方式是push_back,表示將數據添加到vector的尾部,并且按照需要來分配內存,如

for(int i = 0 ; i < 10; i ++)

v.push_back(Widget(i));

 

如果想獲取vector v的大小,但不知道它是否為空,或者已經包含了數據,可用如下代碼實現

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

 

訪問vector中的數據有兩種方法vector::at()  和  vector::operator[],其中vector::at()進行了邊界檢查

 

vector<int>v;                 //定義了vector對象

v.reserve(10);                    //分配空間但是沒有初始化

for(int i = 0 ; i < 7; i++)

v. push_back(i);}

int iVal1 =v[7];                   //不進行邊界檢查

int iVal2 =v.at(7);          //進行邊界檢查

 

deque容器是一個雙端隊列,存放的元素不是以連續的方式存放的

list容器是一種鏈表的實現,儲存的元素是通過使用雙向鏈表實現的

 

55,什么是迭代器的范圍

答:迭代器是STL提供的對一個容器中的對象的訪問方法,定義了容器中對象的范圍,迭代器就如同一個指針。

vector<int>v;    //聲明vector變量

v.push_back(2);   //插入數據

v.push_back(1);

vector<int>::iteratorfirst =v.begin();     //獲取vector<int>的一個元素的迭代器

while1(first !=v.end())          //使用迭代器遍歷vector,一直到最后一個元素

{

   int i =*first;    //獲取迭代器指向的元素的值

first++;

}

 

55,C++如何實現泛型編程

答:泛型編程實現了于特定類型的操作算法,由編譯器根據泛型的調用所傳遞的類及模板生成該類型專用的代碼。

include<iostream>

#include<string>

using namespaces std;

template<class T>

T Add(T a, T b)

{

    Tresult;          // 使用參數化的類型定義變量

   result = a +b;

  return result;

}

int main(int argc, char* argv[])

{

 cout<<”2+3=”<<Add(2,3)<<endl;  

 cout<<”sdf+123=”<<Add(string(“sdf”),string(“123”));

   return 0;

}

 

56,參數傳遞的方式和多態參數傳遞的實現

答:參數傳遞有傳值,傳指針,或者是引用等三種,下面做詳細的介紹

1)傳值方式適合一般的數值傳遞,并且不改變原數據,但是要消耗內存空間

2)傳遞指針方式適合傳遞數組和指針,由于傳遞的是地址,所以直接操作會改變原數據

3)引用方式和指針方式比較類似,是相對比較新的一種方式,一般情況下能用傳地址的就能用引用

而且使用引用更方便一些

實現多態主要是采用指針和引用,傳值方式是復制數據,其類型編譯器就已經決定,而多態是類型要等到執行器才能決定,

所以不適用傳值方式來實現多態參數傳遞

 

57,C++和C定義結構體區別是什么?

答:C++中的結構和類其實具備幾乎一樣的功能,結構體內也是可以聲明函數,C++的結構體和類默認具有不一樣的訪問屬性


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲国产精品成人va在线观看| 欧洲成人在线观看| 久久久精品久久久久| 欧美有码在线观看| 国产97免费视| 国产日韩精品综合网站| 美女精品视频一区| 欧美成人中文字幕| 日韩精品在线免费观看| 日韩视频免费在线| 国内成人精品视频| 精品国偷自产在线| 国产一区二区三区欧美| 国产精品久久久久影院日本| 久久91亚洲精品中文字幕奶水| 日韩精品在线电影| 中文字幕综合在线| 欧美黑人又粗大| 一区二区三区日韩在线| 狠狠色噜噜狠狠狠狠97| 一区二区三区视频免费| 亚洲午夜性刺激影院| 91最新在线免费观看| 日本19禁啪啪免费观看www| 日韩中文视频免费在线观看| 在线精品91av| 国产精品久久久久久久久影视| 亚洲精品久久久久久久久久久久| 国产精品大片wwwwww| 亚洲一二三在线| 久久综合伊人77777| 欧美性受xxx| 久久精品国产96久久久香蕉| 久热精品视频在线| 精品中文字幕久久久久久| 亚洲图片欧美午夜| 国产精品成人一区二区三区吃奶| 色综合久综合久久综合久鬼88| 久久精品国产一区二区电影| 欧美成人三级视频网站| 国产精品jizz在线观看麻豆| 亚洲色图国产精品| 欧美第一黄色网| 91美女片黄在线观| 欧美日本中文字幕| 欧美视频免费在线观看| 久久九九全国免费精品观看| 91丝袜美腿美女视频网站| 久久91精品国产91久久跳| 亚洲国产91精品在线观看| 国产999精品| 国产精品扒开腿爽爽爽视频| 亚洲国产成人久久综合一区| 国产欧美一区二区三区久久人妖| 亚洲天堂免费视频| 久久久国产一区二区三区| 中文字幕久久久av一区| 亚洲精品国产精品国自产在线| 国产偷国产偷亚洲清高网站| 欧美精品在线第一页| 精品国偷自产在线视频99| 亚洲精品一区二区网址| 国产黑人绿帽在线第一区| 亚洲第一福利视频| 日韩国产激情在线| 国产男女猛烈无遮挡91| 国产精品久久久久久婷婷天堂| 欧美自拍视频在线观看| 九九久久国产精品| 国产精品三级久久久久久电影| 日韩在线观看免费全| 午夜精品久久久久久99热| 日韩av大片免费看| 亚洲激情 国产| 国产精品成久久久久三级| 激情成人在线视频| 日韩福利伦理影院免费| 亚洲欧洲高清在线| 国产精品流白浆视频| 在线视频精品一| 亚洲成人三级在线| 久久夜色精品国产| 亚洲最新av在线网站| 91国产视频在线| 一本色道久久88综合日韩精品| 黑人巨大精品欧美一区二区免费| 色偷偷av一区二区三区乱| 97精品欧美一区二区三区| 一本大道久久加勒比香蕉| 亚洲精品视频在线观看视频| 亚洲free嫩bbb| 日本一欧美一欧美一亚洲视频| 日韩精品中文字幕视频在线| 国产精品视频播放| 久久久久久伊人| 色婷婷久久av| 日本一区二区三区在线播放| 55夜色66夜色国产精品视频| 欧美专区中文字幕| 欧美成年人视频网站欧美| 久久国产精品亚洲| 欧美日韩久久久久| 日韩在线观看成人| 欧美国产亚洲精品久久久8v| 91精品久久久久久久久不口人| 国产精品劲爆视频| 欧美最顶级丰满的aⅴ艳星| 欧美日韩一区免费| 亚洲精品视频免费| 欧美性做爰毛片| 乱亲女秽乱长久久久| 国产精品一区二区三区毛片淫片| 91久久久久久久久久| 亚洲一区二区三区乱码aⅴ蜜桃女| 亚洲人成77777在线观看网| 欧美黑人一区二区三区| 国产在线不卡精品| 国产精品毛片a∨一区二区三区|国| 亚洲美女av在线播放| www欧美xxxx| 日韩在线免费视频| www.欧美免费| 色噜噜狠狠狠综合曰曰曰88av| 最新国产成人av网站网址麻豆| 欧美日韩国产中文精品字幕自在自线| 欧美精品亚州精品| 久久久999精品免费| 日韩精品免费看| 欧美日韩中文字幕日韩欧美| 亚洲aa中文字幕| 亚洲国语精品自产拍在线观看| 日韩电影在线观看免费| 欧美有码在线观看| 久久久久久网站| 国产精品黄视频| 91精品视频网站| 亚洲美女久久久| 亚洲国产古装精品网站| 日本久久亚洲电影| 日韩在线小视频| 国产成人精品视| 亚洲尤物视频网| 日韩欧美在线视频日韩欧美在线视频| 日韩久久免费电影| 麻豆精品精华液| 成人伊人精品色xxxx视频| 亚洲第一在线视频| 91禁外国网站| 91av网站在线播放| 日韩欧美a级成人黄色| 亚洲自拍偷拍视频| 久久99青青精品免费观看| 国产精品第三页| 日韩av在线免费播放| 久久久国产精品亚洲一区| 欧美亚洲成人免费| 欧美成人一区在线| 国产欧美一区二区三区久久人妖| 欧美在线视频播放| 国产日韩欧美视频在线| 国产成人免费91av在线| 国产午夜精品一区理论片飘花| 亚洲精品wwww| 91爱爱小视频k|