C/C++ 筆試、面試題目彙總
C++的基礎知識,筆試面試必備
1.求下面函式的返回值( 微軟)
int func(x){
int countx = 0 ;
while (x)
{
countx ++ ;
x = x & (x - 1 );
}
return countx;
}
假定x = 9999。 答案:8
思路:將x轉化為2進位制,看含有的1的個數。
2. 什麼是“引用”?申明和使用“引用”要注意哪些問題?
答:引用就是某個目標變數的“別名”(alias),對應用的操作與對變數直接操作效果完全相同。申明一個引用的時候,切記要對其進行初始化。引用宣告完畢後,相當於目標變數名有兩個名稱,即該目標原名稱和引用名,不能再把該引用名作為其他變數名的別名。宣告一個引用,不是新定義了一個變數,它只表示該引用名是目標變數名的一個別名,它本身不是一種資料型別,因此引用本身不佔儲存單元,系統也不給引用分配儲存單元
3. 將“引用”作為函式引數有哪些特點?
(1)傳遞引用給函式與傳遞指標的效果是一樣的。這時,被調函式的形參就成為原來主調函式中的實參變數或物件的一個別名來使用,所以在被調函式中對形參變數的操作就是對其相應的目標物件(在主調函式中)的操作。
(2)使用引用傳遞函式的引數,在記憶體中並沒有產生實參的副本,它是直接對實參操作;而使用一般變數傳遞函式的引數,當發生函式呼叫時,需要給形參分配儲存單元,形參變數是實參變數的副本;如果傳遞的是物件,還將呼叫拷貝建構函式。因此,當引數傳遞的資料較大時,用引用比用一般變數傳遞引數的效率和所佔空間都好。
(3)使用指標作為函式的引數雖然也能達到與使用引用的效果,但是,在被調函式中同樣要給形參分配儲存單元,且需要重複使用"*指標變數名"的形式進行運算,這很容易產生錯誤且程式的閱讀性較差;另一方面,在主調函式的呼叫點處,必須用變數的地址作為實參。而引用更容易使用,更清晰。
4. 在什麼時候需要使用“常引用”?
如果既要利用引用提高程式的效率,又要保護傳遞給函式的資料不在函式中被改變,就應使用常引用。常引用宣告方式:const 型別識別符號 &引用名=目標變數名;
例1
int a;const int & ra = a;
ra = 1 ; // 錯誤
a = 1 ; // 正確
例2
string foo( );void bar( string &s)
// 那麼下面的表示式將是非法的:
bar(foo( ));
bar( " hello world " );
原因在於foo( )和"hello world"串都會產生一個臨時物件,而在C++中,這些臨時物件都是const型別的。因此上面的表示式就是試圖將一個const型別的物件轉換為非const型別,這是非法的。
引用型引數應該在能被定義為const的情況下,儘量定義為const 。
5. 將“引用”作為函式返回值型別的格式、好處和需要遵守的規則?
格式:
型別識別符號 & 函式名(形參列表及型別說明){
// 函式體
}
好處:在記憶體中不產生被返回值的副本;(注意:正是因為這點原因,所以返回一個區域性變數的引用是不可取的。因為隨著該區域性變數生存期的結束,相應的引用也會失效,產生runtime error!
注意:
(1)不能返回區域性變數的引用。這條可以參照Effective C++[1]的Item 31。主要原因是區域性變數會在函式返回後被銷燬,因此被返回的引用就成為了"無所指"的引用,程式會進入未知狀態。
(2)不能返回函式內部new分配的記憶體的引用(這個要注意啦,很多人沒意識到,哈哈。。。)。 這條可以參照Effective C++[1]的Item 31。雖然不存在區域性變數的被動銷燬問題,可對於這種情況(返回函式內部new分配記憶體的引用),又面臨其它尷尬局面。例如,被函式返回的引用只是作為一個臨時變量出現,而沒有被賦予一個實際的變數,那麼這個引用所指向的空間(由new分配)就無法釋放,造成memory leak。
(3)可以返回類成員的引用,但最好是const。 這條原則可以參照Effective C++[1]的Item 30。主要原因是當物件的屬性是與某種業務規則(business rule)相關聯的時候,其賦值常常與某些其它屬性或者物件的狀態有關,因此有必要將賦值操作封裝在一個業務規則當中。如果其它物件可以獲得該屬性的非常量引用(或指標),那麼對該屬性的單純賦值就會破壞業務規則的完整性。
(4)流操作符過載返回值申明為“引用”的作用:
流操作符<<和>>,這兩個操作符常常希望被連續使用,例如:cout <<"hello" << endl; 因此這兩個操作符的返回值應該是一個仍然支援這兩個操作符的流引用。可選的其它方案包括:返回一個流物件和返回一個流物件指標。但是對於返回一個流物件,程式必須重新(拷貝)構造一個新的流物件,也就是說,連續的兩個<<操作符實際上是針對不同物件的!這無法讓人接受。對於返回一個流指標則不能連續使用<<操作符。 因此,返回一個流物件引用是惟一選擇。這個唯一選擇很關鍵,它說明了引用的重要性以及無可替代性,也許這就是C++語言中引入引用這個概念的原因吧。 賦值操作符=。這個操作符象流操作符一樣,是可以連續使用的,例如:x = j = 10;或者(x=10)=100;賦值操作符的返回值必須是一個左值,以便可以被繼續賦值。因此引用成了這個操作符的惟一返回值選擇。
例3
#include < iostream.h >int & put( int n);
int vals[ 10 ];
int error = - 1 ;
void main()
{
put( 0 ) = 10 ; // 以put(0)函式值作為左值,等價於vals[0]=10;
put( 9 ) = 20 ; // 以put(9)函式值作為左值,等價於vals[9]=20;
cout << vals[ 0 ];
cout << vals[ 9 ];
}
int & put( int n)
{
if (n >= 0 && n <= 9 ) {
return vals[n]; } else { cout << " subscript error " ; return error; } }
(5)在另外的一些操作符中,卻千萬不能返回引用:+-*/ 四則運算子。它們不能返回引用,Effective C++[1]的Item23詳細的討論了這個問題。主要原因是這四個操作符沒有side effect,因此,它們必須構造一個物件作為返回值,可選的方案包括:返回一個物件、返回一個區域性變數的引用,返回一個new分配的物件的引用、返回一 個靜態物件引用。根據前面提到的引用作為返回值的三個規則,第2、3兩個方案都被否決了。靜態物件的引用又因為((a+b) == (c+d))會永遠為true而導致錯誤。所以可選的只剩下返回一個物件了。
6. “引用”與多型的關係?
引用是除指標外另一個可以產生多型效果的手段。這意味著,一個基類的引用可以指向它的派生類例項。
例4
Class A;Class B : Class A
{
// ...
};
B b;
A & ref = b;
7. “引用”與指標的區別是什麼?
指標通過某個指標變數指向一個物件後,對它所指向的變數間接操作。程式中使用指標,程式的可讀性差;
而引用本身就是目標變數的別名,對引用的操作就是對目標變數的操作。此外,就是上面提到的對函式傳ref和pointer的區別。
8. 什麼時候需要“引用”?
流操作符<<和>>、賦值操作符=的返回值、拷貝建構函式的引數、賦值操作符=的引數、其它情況都推薦使用引用。
9. 結構與聯合有和區別?
1. 結構和聯合都是由多個不同的資料型別成員組成, 但在任何同一時刻, 聯合中只存放了一個被選中的成員(所有成員共用一塊地址空間), 而結構的所有成員都存在(不同成員的存放地址不同)。
2. 對於聯合的不同成員賦值, 將會對其它成員重寫, 原來成員的值就不存在了, 而對於結構的不同成員賦值是互不影響的。
10. 下面關於“聯合”的題目的輸出?
a)
#include < stdio.h >union
{
int i;
char x[ 2 ];
}a;
void main()
{
a.x[ 0 ] = 10 ;
a.x[ 1 ] = 1 ;
printf( " %d " ,a.i);
}
答案:266 (低位低地址,高位高地址,記憶體佔用情況是Ox010A)
b)
main(){
union{ /* 定義一個聯合 */
int i;
struct { /* 在聯合中定義一個結構 */
char first;
char second;
}half;
}number;
number.i = 0x4241 ; /* 聯合成員賦值 */
printf( " %c%c\n " , number.half.first, mumber.half.second);
number.half.first = ' a ' ; /* 聯合中結構成員賦值 */
number.half.second = ' b ' ;
printf( " %x\n " ,number.i);
getch();
}
答案: AB (0x41對應'A',是低位;Ox42對應'B',是高位)
6261 (number.i和number.half共用一塊地址空間)
11. 已知strcpy的函式原型:char *strcpy(char *strDest, const char *strSrc)其中strDest 是目的字串,strSrc 是源字串。不呼叫C++/C 的字串庫函式,請編寫函式 strcpy。
答案:
編寫strcpy函式(10分)
已知strcpy函式的原型是
char *strcpy(char *strDest, const char *strSrc);
其中strDest是目的字串,strSrc是源字串。
(1)不呼叫C++/C的字串庫函式,請編寫函式 strcpy
(2)strcpy能把strSrc的內容複製到strDest,為什麼還要char * 型別的返回值?
答:為了 實現鏈式表示式。 // 2分
例如 int length = strlen( strcpy( strDest, “hello world”) );
*/
#include < assert.h >
#include < stdio.h >
char * strcpy( char * strDest, const char * strSrc)
{
assert((strDest != NULL) && (strSrc != NULL)); // 2分
char * address = strDest; // 2分
while ( ( * strDest ++ = * strSrc ++ ) != ' \0 ' ) // 2分
NULL;
return address ; // 2分
}
另外strlen函式如下:
#include < stdio.h >
#include < assert.h >
int strlen( const char * str ) // 輸入引數const
{
assert( str != NULL ); // 斷言字串地址非0
int len = 0;
while ( ( * str ++ ) != ' \0 ' )
{
len ++ ;
}
return len;
}
12. 已知String類定義如下:
class String
{
public :
String(const char * str = NULL); // 通用建構函式
String(const String & another); // 拷貝建構函式
~ String(); // 解構函式
String & operater = ( const String & rhs); // 賦值函式
private :
char * m_data; // 用於儲存字串
};
嘗試寫出類的成員函式實現。
答案:
String::String( const char * str){
if ( str == NULL ) // strlen在引數為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,other.m_data);
}
String & String:: operator = ( const String & rhs)
{
if ( this == & rhs)
return * this ;
delete []m_data; // 刪除原來的資料,新開一塊記憶體
m_data = new char [strlen(rhs.m_data) + 1 ];
strcpy(m_data,rhs.m_data);
return * this ;
}
String:: ~ String()
{
delete []m_data ;
}
13. .h標頭檔案中的ifndef/define/endif 的作用?
答:防止該標頭檔案被重複引用。
14. #include<file.h> 與#include "file.h"的區別?
答:前者是從Standard Library的路徑尋找和引用file.h,而後者是從當前工作路徑搜尋並引用file.h。
15.在C++程式中呼叫被C 編譯器編譯後的函式,為什麼要加extern “C”?
首先,作為extern是C/C++語言中表明函式和全域性變數作用範圍(可見性)的關鍵字,該關鍵字告訴編譯器,其宣告的函式和變數可以在本模組或其它模組中使用。
通常,在模組的標頭檔案中對本模組提供給其它模組引用的函式和全域性變數以關鍵字extern宣告。例如,如果模組B欲引用該模組A中定義的全域性變數和函式時只需包含模組A的標頭檔案即可。這樣,模組B中呼叫模組A中的函式時,在編譯階段,模組B雖然找不到該函式,但是並不會報錯;它會在連線階段中從模組A編譯生成的目的碼中找到此函式
extern "C"是連線申明(linkage declaration),被extern "C"修飾的變數和函式是按照C語言方式編譯和連線的,來看看C++中對類似。
C的函式是怎樣編譯的:
作為一種面向物件的語言,C++支援函式過載,而過程式語言C則不支援。函式被C++編譯後在符號庫中的名字與C語言的不同。例如,假設某個函式的原型為:
void foo( int x, int y );
該函式被C編譯器編譯後在符號庫中的名字為_foo,而C++編譯器則會產生像_foo_int_int之類的名字(不同的編譯器可能生成的名字不同,但是都採用了相同的機制,生成的新名字稱為“mangled name”)。
_foo_int_int 這樣的名字包含了函式名、函式引數數量及型別資訊,C++就是靠這種機制來實現函式過載的。例如,在C++中,函式void foo( int x, int y )與void foo( int x, float y )編譯生成的符號是不相同的,後者為_foo_int_float。
同 樣地,C++中的變數除支援區域性變數外,還支援類成員變數和全域性變數。使用者所編寫程式的類成員變數可能與全域性變數同名,我們以"."來區分。而本質上,編譯器在進行編譯時,與函式的處理相似,也為類中的變數取了一個獨一無二的名字,這個名字與使用者程式中同名的全域性變數名字不同。
未加extern "C"宣告時的連線方式
假設在C++中,模組A的標頭檔案如下:
// 模組A標頭檔案 moduleA.h#ifndef MODULE_A_H
#define MODULE_A_H
int foo( int x, int y );
#endif
在模組B中引用該函式:
// 模組B實現檔案 moduleB.cpp#include " moduleA.h "
foo( 2 , 3 );
實際上,在連線階段,聯結器會從模組A生成的目標檔案moduleA.obj中尋找_foo_int_int這樣的符號!
加extern "C"聲明後的編譯和連線方式
加extern "C"聲明後,模組A的標頭檔案變為:
// 模組A標頭檔案 moduleA.h#ifndef MODULE_A_H
#define MODULE_A_H
extern " C " int foo( int x, int y );
#endif
在模組B的實現檔案中仍然呼叫foo( 2,3 ),其結果是:
(1)模組A編譯生成foo的目的碼時,沒有對其名字進行特殊處理,採用了C語言的方式;
(2)聯結器在為模組B的目的碼尋找foo(2,3)呼叫時,尋找的是未經修改的符號名_foo。
如果在模組A中函式聲明瞭foo為extern "C"型別,而模組B中包含的是extern int foo( int x, int y ) ,則模組B找不到模組A中的函式;反之亦然。
所以,可以用一句話概括extern “C”這個宣告的真實目的(任何語言中的任何語法特性的誕生都不是隨意而為的,來源於真實世界的需求驅動。我們在思考問題時,不能只停留在這個語言是怎麼做的,還要問一問它為什麼要這麼做,動機是什麼,這樣我們可以更深入地理解許多問題):實現C++與C及其它語言的混合程式設計。
明白了C++中extern "C"的設立動機,我們下面來具體分析extern "C"通常的使用技巧:
extern "C"的慣用法
(1)在C++中引用C語言中的函式和變數,在包含C語言標頭檔案(假設為cExample.h)時,需進行下列處理:
extern " C "{
#include " cExample.h "
}
而在C語言的標頭檔案中,對其外部函式只能指定為extern型別,C語言中不支援extern "C"宣告,在.c檔案中包含了extern"C"時會出現編譯語法錯誤。
C++引用C函式例子工程中包含的三個檔案的原始碼如下:
/* c語言標頭檔案:cExample.h */#ifndef C_EXAMPLE_H
#define C_EXAMPLE_H
extern int add( int x, inty);
#endif
/* c語言實現檔案:cExample.c */
#include " cExample.h "
int add( int x, int y )
{
return x + y;
}
// c++實現檔案,呼叫add:cppFile.cpp
extern " C "
{
#include " cExample.h "
}
int main( int argc, char * argv[])
{
add( 2 , 3 );
return 0 ;
}
如果C++呼叫一個C語言編寫的.DLL時,當包括.DLL的標頭檔案或宣告介面函式時,應加extern "C" { }。
(2)在C中引用C++語言中的函式和變數時,C++的標頭檔案需新增extern "C",但是在C語言中不能直接引用聲明瞭extern "C"的該標頭檔案,應該僅將C檔案中將C++中定義的extern"C"函式宣告為extern型別。
C引用C++函式例子工程中包含的三個檔案的原始碼如下:
// C++標頭檔案cppExample.h#ifndef CPP_EXAMPLE_H
#define CPP_EXAMPLE_H
extern " C " int add( int x, int y );
#endif
// C++實現檔案 cppExample.cpp
#include " cppExample.h "
int add( int x, int y )
{
return x + y;
}
/* C實現檔案 cFile.c
/* 這樣會編譯出錯:#i nclude "cExample.h" */
extern int add( int x, int y );
int main( int argc, char * argv[] )
{
add( 2 , 3 );
return 0 ;
}
16. 關聯、聚合(Aggregation)以及組合(Composition)的區別?
涉及到UML中的一些概念:
關聯是表示兩個類的一般性聯絡,比如“學生”和“老師”就是一種關聯關係;
聚合表示has-a的關係,是一種相對鬆散的關係,聚合類不需要對被聚合類負責,如下圖所示,用空的菱形表示聚合關係:
從實現的角度講,聚合可以表示為:
class A {...} class B { A* a; .....}
組合表示contains-a的關係,關聯性強於聚合:組合類與被組合類有相同的生命週期,組合類要對被組合類負責,採用實心的菱形表示組合關係:
實現的形式是:
class A{...} class B{ A a; ...}
17.面向物件的三個基本特徵,並簡單敘述之?
1. 封裝:將客觀事物抽象成類,每個類對自身的資料和方法實行protection(private, protected,public)
2. 繼承:廣義的繼承有三種實現形式:實現繼承(指使用基類的屬性和方法而無需額外編碼的能力)、可視繼承(子窗體使用父窗體的外觀和實現程式碼)、介面繼承(僅使用屬性和方法,實現滯後到子類實現)。前兩種(類繼承)和後一種(物件組合=>介面繼承以及純虛擬函式)構成了功能複用的兩種方式。
3. 多型:系統能夠在執行時,能夠根據其型別確定呼叫哪個過載的成員函式的能力,稱為多型性。
18. 過載(overload)和重寫(overried,有的書也叫做“覆蓋”)的區別?
常考的題目。
從定義上來說:
相關推薦
C/C++ 筆試、面試題目彙總(續)
一.找錯題 試題1: void test1() { char string [ 10 ]; char * str1 = " 0123456789 " ; strcpy(&nb
C/C++ 筆試、面試題目彙總
C++的基礎知識,筆試面試必備 1.求下面函式的返回值( 微軟) int func(x) { int countx = 0 ;&
C/C++ 筆試、面試題目大彙總2
一.找錯題 試題1: void test1() { charstring[10]; char* str1 ="0123456789"; strcpy( string, str1 ); } 試題2: void test2() { charstring[1
Linux C++後臺開發面試題目彙總
資料庫: 1.資料庫中什麼是事務?事務的隔離級別?事務的四個特性?什麼事髒讀、幻讀、不可重複讀? 事務是一種手段,通過事務,我們可以將一系列的資料庫操作組合在一起作為一個整體進行操作
C++筆試、面試、基礎問題筆記
一、sizeof和strlen strlen所作的僅僅是一個計數器的工作,它從記憶體的某個位置(可以是字串開頭,中間某個位置,甚至是某個不確定的記憶體區域)開始掃描,直到碰到第一個字串結束符'/0'為止,然後返回計數器值。 1. char* p = new char[100
C++ 複習要點、面試常見問題總結
本文總結一下C++面試時常遇到的問題。C++面試中,主要涉及的考點有: 關鍵字極其用法,常考的關鍵字有const, sizeof, typedef, inline, static, extern, new, delete等等 語法問題 型別轉換 指標以及指標和引用的區別 面向物件的相關
C++軟體開發經典面試題目
1、 Static有什麼用途? (1)函式體內static變數的作用範圍是該函式體,該變數的記憶體只被分配一次,因此它的值在下次呼叫時不變; (2)模組內的static全域性變數同樣只能在該模組內的函式訪問和呼叫,不能被模組外的其他函式訪問; (3)在
2019阿里、騰訊等大廠技術面試題目彙總
Github地址:https://github.com/0voice/interview_internal_reference
面試題目彙總(JAVA演算法/資料結構)
1.題目:輸入一個正整數陣列,把數組裡所有數字拼接起來排成一個數,列印能拼接出的所有數字中最小的一個。例如輸入陣列{3,32,321},則打印出這三個數字能排成的最小數字為321323。 程式碼: import java.util.Arr
python面試題目彙總
參考:https://www.cnblogs.com/JetpropelledSnake/p/9396511.html#_label1 1、常見的PEP8規範? 縮排:4個空格 空行:函式與函式之間空兩行,類內部的函式之間空一行 命名: 1、函式名小寫,可採用下劃線加字母;類名單詞第一個字母大寫,採用
2017最新PHP經典面試題目彙總(上篇)
1、雙引號和單引號的區別 雙引號解釋變數,單引號不解釋變數 雙引號裡插入單引號,其中單引號裡如果有變數的話,變數解釋 雙引號的變數名後面必須要有一個非數字、字母、下劃線的特殊字元,或者用{}講變數括起來,否則會將變數名後面的部分當做一個整體,引起語法錯誤 雙引號解釋轉義字元
[置頂]2017最新PHP經典面試題目彙總(上篇)
本文章將持續更新,希望能在評論區發表自己的見解和認為比較經典的題目,後續筆者會在適當的節點對本文章進行分類和層次劃分。文章中的不足之處望多指點,糾正! 1、雙引號和單引號的區別 雙引號解釋變數,單引號不解釋變數 雙引號裡插入單引號,其中單引號裡如果有變數的話,變數解釋 雙
Java面試題目彙總
mysql鎖機制 ? 什麼是悲觀鎖? 悲觀鎖如何鎖表? 什麼是樂觀鎖? 樂觀鎖如何應用 ? Mysql儲存引擎有哪幾種?有什麼區別? 框架中常用的設計模式有哪些? 代理模式的優點? 代理模式的應用? Java 代理模式和裝飾者模式的區別? Spring攔截器實現? 使用者不斷增多 如何把
HTML5面試題目彙總(一)
2、行內元素有哪些?塊級元素有哪些? 空(void)元素有那些?答案解析:行內元素:a b span img input select strong 塊級元素:div ul ol li dl dt dd h1 h2 h3 h4 p 等 空元素:<br> <
某網貼出來的u3d面試題目彙總,當時學習下(好多我都不會呢)
在蠻牛網看到這個東西,原作者我也沒注意是誰,看了下很多知識我都不會呀,算是學習一下吧,這裡貼出來,大家看看。 第一部分 1.請簡述值型別與引用型別的區別 2.C#中所有引用型別的基類是什麼 3.請簡述ArrayList和List<Int>的主要區別 4
筆試、面試重點總結:WIN32、MFC與Linux
win321. Win32應用程式的基本型別.2. 建立win32視窗程式的幾個步驟,及使用到的函式。3. nmake 與 makefile。4. 有哪些字符集? Win32對於各種字符集如何進行相容及轉換? (wchar_t、TCHAR、TEXT() )。5. 怎麼建立一個子視窗?在哪進行設定?6. 視窗類
2015美團演算法工程師筆試、面試之旅
9月16日下午進行了美團筆試,8個大題+若干附加題(其它崗位選做),筆試題就不多說了,基本都是小演算法題,寫思想任何寫程式碼,相信網上都能搜到。90分鐘時間,我做了6題,時間實在是來不及,做完感覺進面試應該沒問題。 當天晚上,由於實驗室任務
C/C++ 之 多執行緒 百度、華為、360 面試面試題彙總(一)
以下提供答案參考: 第一題:執行緒的基本概念、執行緒的基本狀態及狀態之間的關係? 執行緒,有時稱為輕量級程序,是CPU使用的基本單元;它由執行緒ID、程式計數器、暫存器集合和堆疊組成。它與屬於同一程序的其他執行緒共享其程式碼段、資料段和其他作業系統資源(如開啟檔案和訊號)。
C++常見筆試面試題目:string類的拷貝賦值運算子函式
要求:寫出一個String類的賦值運算子函式 注意事項: (1)返回值的型別需宣告為該型別的引用,並在函式結束前返回例項自身的引用(即*this),因為只有返回一個引用,才可以允許連續賦值。 (2)傳入引數必須為常量的引用。常量確保在函式內不改變傳入例項的
C# .Net經典面試題目及答案
數字 空類 相同 面向連接 tab session cnblogs 一個 all 1, 請你說說.NET中類和結構的區別? 答: 結構和類具有大體的語法,但是結構受到的限制比類要多。結構不能申明有默認的構造函數,為結構的副本是又編譯器創建和銷毀的,所以不需要默認的構造函