首页 > 代码库 > C++考点问答题

C++考点问答题

实参和形参的区别是什么?

答:形参是“形式化的参数”,相当于函数中的自变量,?而实参是形参的初始值, 相当于自变量所取的值。 

 

请指出下列函数哪个有错误  

(a) int f() { string s;         

   // ...         

   return s; }     

(b) f2(int i) { /* ... */ }     

(c) int calc(int v1, int v1) /* ... */ }     

(d) double square(double x) return x * x;

答:(a)错误在于f()返回类型为int,所以不可以返回string型的s.可改为:     

string f() { string s;         

// ...         

return s; }          

(b)错误在于没有返回类型,可改为:     

void f2(int i) { /* ... */ }          

(c)错误在于函数体的括号缺左半部分。可改为:     

int calc(int v1, int v1) {/* ... */ }          

(d)错误在于函数体没有使?用括号括起来,可改为:     

double square(double x) { return x * x; }   

  

说明形参、局部变量及局部静态变量的区别。编写一个函数,同时用到这三种形式。

答: 形参相当于函数的自变量,其作用域为函数声明与定义的范围。 局部变量是在函数体中所声明并定义的变量,其作用域在该函数体内。局部静态变量为在函数体中声明的变量,但其作?用域是在此函数体及函数体后?面程序段落中,生物周期自它被声明之时起,?至整个程序结束终?止。 

函数?示例及变量说明如下:

void func(int intpara) //intpara为形参。

{

    int localvar;  //localvar为局部变量。

    static int localstavar;  //localstavar为局部静态变量。

    return;

}

 

假设T是某种类型的名字,说明以下两个函数声明的区别:?一个是 void f(T),另?一个是void f(&T)

答:前者说明其只有一个形参,且类型为T.以一个类型为T的实参调?用该函数,调?用过程不改变实参本?身的值。 后者说明其只有?个形参,且是一个引?用型形参,被引?用变量类型为T.以类型为T的实参调?用该 函数时,实参在函数作?用域内可能被改变。 

 

 

为下?的函数编写函数声明,从给定的名字中推测函数具备的功能。 

(a)名为compare的函数,返回布尔值,两个参数都是matrix类的引?用。 

(b)名为change_value的函数,返回vector<int>的迭代器,有两个参数:?个是int,另?个是 vector<int>的迭代器。

bool compare(matrix &mat1, matrix &mat2); //该函数功能应是比较两个matrix类的对象的大小。

vector<int>::iterator change_value(int val, vector<int>::iterator iter);//功能应是更动vector中指定位置的值,并返回对应迭代器。

 

在error_msg函数的第二个版本中包含有Errcode类型的参数,其中循环内的elem是什么类型? 

答:elemconst std::string&类型。

 

编写?个函数的声明,使其返回数组的引?用并且该数组包含10string对象。不要使?用位置返回类型、decltype或者类型别名。

答:string (&func())[10]

 

说明在下面的每组声明中第?条声明语句是何含义。如果有非法的声明,请指出来。 

Int calc(int,int);

答: (a)中第二句非法,它对第一句中的函数进?行了重复声明。 

(b)中第二名是非法声明,因为它与第一句形参完全相同,返回类型不同; 

(c)中第二句合法。 

 

下面的哪个调用是非法的?为什么?哪个调?用虽然合法但显然与程序员的初衷不符?为什么? char *init(int ht, int wd = 80, char bckgrnd = ‘ ); (a) init();(b) init(24,10);(c) init(14, ‘*‘); 

答: (a)非法,因为第一个形参并?无默认初始化参数,因此?无法执行该调?用。 

(b)合法。 

(c)虽然合法,但与程序员初衷不符。因为该调?用执?行时向14被传递为ht,*’被传递给wd,bckgrnd 被默认初始化为空字符。程序员的期望是wd被传值14. 

 

说明下?循环的含义,它对assert的使?合理吗? string s;while (cin >> s && s != sought) { } // empty body  assert(cin); 

答:代码中对assert的使用是不合理的。assert适于检查不能发生的条件,?而该句中只要用户有 输入cin便为trueassert就将发生。 将其改为assert(s == sought)更为合理。

 

已知有第217页对函数f的声明,对于下面的每一个调用列出可?函数。其中哪个函数是最佳匹配?如果调?用不合法,是因为没有可匹配的函数还是因为调用具有?义性? (a) f(2.56, 42)  (b) f(42) (c) f(42, 0) (d) f(2.56, 3.14) 

答: (a)void f(int,int)void f(double, double = 3.14)为可行函数。没有最佳匹配,调用不合法,因为 调用具有?义性。 (b)void f(int)void f(double, double = 3.14)为可行函数。前者是最佳匹配。 (c)void f(int,int)void f(double, double = 3.14)为可行函数。前者为最佳匹配。 (d)void f(int,int)void f(double, double = 3.14)为可行函数。后者为最佳匹配。

 

编写函数的声明,令其接受两个int形参并且返回类型也是int;然后声明一个vector对象,令其元素是指向该函数的指针。

Int f(int,int);

Using pF=declatype(f)*;

Vector<pF>vec;

 

下?面哪些句?子是合法的?如果有不合法的句?子,请说明为什么? (a) const int buf;     (b) int cnt = 0; (c) const int sz = cnt;    (d) ++cnt; ++sz;

答: (a)不合法,因为const对象?一旦创建必须被初始化; (b)合法。 (c)合法; (d)不合法,sz是常量,其值不能改变。

 

下?面的哪些初始化是合法的?请说明原因。 (a) int i = -1, &r = 0;   (b) int *const p2 = &i2; (c) const int i = -1, &r = 0;  (d) const int *const p3 = &i2; (e) const int *p1 = &i2;   (f) const int &const r2; (g) const int i2 = i, &r = i; 

答: (a)不合法,r是引?用,必须在声明语句中定义它所被绑定的对象; (b)只要前?面已经定义i2int型变量,则该句合法,p2是?一个常量指针,它指向i2. (c)合法。 (d)只要i2在该句前已被声明为int类型,则该句合法。 (e)i2int类型,则该句合法。 (f)不合法,r2是对?一个int类型常量的常量引?用,它必须被初始化。 (g)i已被声明为int类型,则此句合法,否则不合法。

 

假设已有上?个练习中定义的那些变量,则下?面的哪些语句是合法 的?请说明原因。 (a) i = ic;      (b) p1 = p3; (c) p1 = ?      (d) p3 = ? (e) p2 = p1;      (f) ic = *p3;

答: (a)合法,前提是ic已被正确定义了(上例中ic被声明为int常量,但未被初始化,语句非法。) (b)不合法:p3是指向常量int的常量指针,?而p1是普通int类型指针。 (c)不合法,p1是普通int型指针,?而icint型常量。 (d)不合法,p3是常量指针,它应该在声明时被初始化,此后不能再赋值。 (e)不合法,p2是常量指针,不能通过拷?贝的?方法对其赋值。 (f)不合法,icint类型常量,只能在声明语句中初始化,此后不能通过拷贝完成赋值。 

 

对于下?面的这些语句,请说明对象被声明成了顶层const还是底层 const? const int v2 = 0;     int v1 = v2;   int *p1 = &v1, &r1 = v1;   const int *p2 = &v2, *const p3 = &i, &r2 = v2; 

答: v2是顶层const(因为它自己是常量); v1不是const; p1指向的v1不是const,它自己也不是const,所以既不是顶层const也不是底层const; r1v1的引用,而v1不是const,因此r1也不是const; p2指向const int,而它本?身不是const,所以它是底层const; p3自己是常量指针,指向常量int数据,因此p3既是顶层const,也是底层const(前提是 i已被定义为int常量); r2int型常量v2的引用,因此它是底层const. 

 

下面的代码是否合法?如果非法,请设法将其修改正确。 int null = 0, *p = null; 

答: 不合法,p是指针,需指向?个int型变量的地址。可改为: int null = 0, *p = &null; 

 

如果想定义?个含有10个元素的vector对象,所有元素的值都是42, 请列举出三种不同的实现?方法。哪种?方法更好呢?为什么? 

答: 第?种方法:vector<int> vec1(10,42); 第?种方法:vector<int> vec2{42,42,42,42,42,42,42,42,42,42} 第三种方法:使?用如下程序段: vector<int> vec3; for(int i=0; i <=9; ++i)     vec3.push_back(42); 第一种?方法最好,因为它比较简洁:)

 

?分搜索程序中,为什么用的是mid = beg + (end - beg) / 2,?非mid = (beg + end) /2;? 

答:因为迭代器没有加法运算。

 

下列数组中元素的值是什么? 

string sa[10]; int ia[10]; int main() { string sa2[10]; int ia2[10];  } 

答: sa中有10个空字符串; ia中有100; sa2ia2由于在函数内部,没被初始化时,是未定义的。

 

相比于vector来说,数组有哪些缺点,请列举一些。

答: 数组不够灵活,它们的维度是固定的,因此要使?用数组时事先要仔细设计其维度,特别 是维度不能?小于所需。 也是由于维度固定,数组不能通过push_back类函数?自由填加元素。

 

指出下面代码中的索引错误。 constexpr size_t array_size = 10;   int ia[array_size];   for (size_t ix = 1; ix <= array_size; ++ix)     ia[ix] = ix;  

答: 这组语句对一个10维数组进?行赋值,它从ia[1]即第二个元素开始赋起,这没有问题。问题在于它的最后一个赋值一句是对ia[10]进?行赋值,?而这个元素是不存在的。

 

根据4.12节中的标表,在下述表达式的合理位置添加括号,使得添加 括号后运算对象的组合顺序与添加括号前?一致。 

(a)  *vec.begin()  (b)  *vec.begin() + 1

答: (a)*(vec.begin()); (b)(*(vec.begin()))+1; 

 

C++语言没有明确规定大多数二元运算符的求值顺序,给编译器优化 留下了余地。这种策略实际上是在代码?生成效率和程序潜在缺陷之间进?行了权衡, 你认为这可以接受吗?请说出你的理由。

答: 这是可以接受的。当C++中采?用这种策略时,编译器可根据需要来即时抉 择求值顺序,从?而实现尽可能?高的执?行效率,程序员若避免写作次序影响 求值结果的代码,可规避程序的潜在执?行缺陷。 与C++不同,JAVA中采取确定执?行次序的策略,此时牺牲了可能的?高效, 但获得了程序结构的清晰与明确。 两者所追求的??目标不同,因此所采取的策略也不同。 

 

解释在下面的if语句中条件部分的判断过程。 

const char *cp = "Hello World";   if (cp && *cp) 

答:先计算cpbool值,由于cp是?非空指针,因此它所对应的bool值为 true,因此再计算*cpbool值,其亦?非0,对应bool值为true,因此条件部 分运算结果为true. 

 

尽管下面的语句合法,但它们实际执行的行为可能和预期并不?一样, 为什么?应该如何修改? (a) if (p = getPtr() != 0)  (b) if (i = 1024)

答:(a) 赋值运算符优先级较低,因此此句等价于if( p = ( getPtr() != 0)), 作者预 期做的条件判断应是判断p= getPtr()0是否相同,因此可将此句改为: if (p = getPtr()) != 0) (b)=是赋值运算符?而不是相等运算符,因此此句应改为if (i == 1024)

 

假设ptr的类型是指向int的指针、vec的类型是vector<int>ival的类 型是int,说明下?面的表达式是何含义?如果有表达式不正确,为什么?应该如何 修改? (a) ptr != 0 && *ptr++    (b) ival++ && ival (c) vec[ival++] <= vec[ival]

答: (a)该式非法。 该式等价于(ptr != 0) && *ptr++))该式当ptr不是空指针 且ptr所指元素?非0时值为true,否则为false,运算之后将ptr向前移动?一个位置,而由于ptr是指向int类型的指针?无法进?行?自增运算,因此该式?非法。可做如下修改 : ptr != 0 && (*ptr)++  (b)该式将产?生未定义结果,其运算过程中明确的是先计算&&左侧的表达式值, 当其为真时计算右侧的值。此处假设ival-1,则其所对应的bool值为true,此时 ival先执?行左侧的?自增计算还是先执?行右侧的bool值计算是不确定的,?而不同的 运算顺序将影响最后结果的得出。不?鼓励使?用类似的表达式。(可参考 C++2011标准?文档(References??目录下The C++ Standard – ANSI ISO-IEC 14882-2011.pdf 中的1.9节)可做如下修改:ival  && (ival + 1); (c)该式将产?生未定义结果,原因同(b),可改为vec[ival] <= vec[ival +1];

 

假设iter的类型vector<string>::iterator,说明下?面的表达式是否合 法。如果合法,表达式的含义是什么?如果不合法,错在何处? (a) *iter++;    (b) (*iter)++;   (c) *iter.empty() (d) iter->empty();  (e) ++*iter;    (f) iter++->empty();

答: (a)合法,后置递增运算符比*优先级?高,因此该表达式等价于*(iter++),?首先计算 iter所指元素值,然后将iter向前移动?一个位置,使其指向下?一个元素; (b)不合法,*iterstring类型,无法进行++运算。 (c)不合法,因为.的优先级?高于解引?用运算符,因此先计算iter.empty(),?而迭代 器类型没有名为empty的成员函数。 (d)合法,等价于(*iter).empty(),由于*iterstring类型,因此该表达式正确。 (e)不合法,*iterstring类型,不适合使?用++运算。 (f)合法,先进行(*iter).empty运算,再将iter向后移动一个位置。

 

在本节关于测验成绩的例子中,如果使用unsigned int作为quiz1的类型会发生什么情况?

答:若所用系统中int使?用16位存储,则?无法容纳全班同学的成绩数据,不能满足表达需要。 

 

下列表达式的结果是什么? 

unsigned long ul1 = 3, ul2 = 7; (a) ul1 & ul2       (b) ul1 | ul2 (c) ul1 && ul2        (d) ul1 || ul2

答:(a)3 (b)7 (c)true (d)true 

 

推断下面代码的输出结果并说明理由。实际运行这段程序,结果和你 想象的?样吗?如果不?样,为什么? int x[10]; int *p = x;   cout << sizeof(x)/sizeof(*x) << endl;   cout << sizeof(p)/sizeof(*p) << endl;  

答:此处sizeof(x)应为数组x所占空间的大小,sizeof(*x)为其?首元素所占空间的大小,因此两者相除,返回数组中元素个数,即第?句应输出10. sizeof(p)为整形指针所占空间的大小(int的地址以long型进行存储,在本人所用系统中该值为 64),*p指向数组x的?首个元素,sizeof(*p)为整形数值所占空间?大?小,为32位,因此第二句输出为2.

 

解释下面这个循环的含义。 

constexpr int size = 5;   int ia[size] = {1,2,3,4,5};   for (int *ptr = ia, ix = 0;   ix != size && ptr != ia+size;   ++ix, ++ptr) { /* . . . */ }  

答:该循环的含义为:自ptr指向数组首部、下标为0的元素起,只要下标尚在合理范围内(即小于数组size时)且指针还指在数组有效元素时,执行循环体中的内容,每次循环体执?行结束时, 将下标加1,指针后移一个元素,继续判断上述循环条件是否为true...

 

假设有如下的定义, 

char cval;      int ival;       unsigned int ui;    ?oat fval;    double dval;   请回答在下面的表达式中发?生了隐式类型转换吗?如果有,指出来。 (a) cval = ‘a‘ + 3;   (b) fval = ui - ival * 1.0; (c) dval = ui * fval;  (d) cval = ival + fval + dval;

答:(a)a’为字符型字?面值,需将其转为int型,与3相加后,所得结束为int型,再 将其转为char类型。 (b)ival先转为double类型与1.0相乘,所得结果为double型,将ui转为double型 参与运算,最后所得结果为double类型,将其转为?oat型。 (c)ui转为?oat类型,与fval相乘,所得?oat类型转为double. (d)ival转为?oat类型与fval相加,将所得结果由?oat型转为double型与dval相加, 所得结果转为char类型。

 

用命名的强制类型转换改写下列旧式的转换语句。 

int i; double d; const string *ps; char *pc; void *pv; (a) pv = (void*)ps;  (b) i = int(*pc); (c) pv = &d;    (d) pc = (char*) pv;

答: (a)pv =static_cast<void *> (const_cast<string *>(ps)); (b)i = static_cast<int>(*pc); (c)pv = static_cast<void *>(&d); (d)pc = reinterpret_cast<char *>(pv);

 

什么是空语句?什么时候会用到空语句?

答:空语句即是只有?一个分号的语句。 当程序段落中语法上需要?一个语句而语义上(逻辑上)并不需要时可使用空语句。

 

说明?nd_char函数中的三个形参为什么是现在的类型,特别说明为什 么s是常量引?用而occurs是普通引用?为什么soccures是引用类型而c不是? 如果令s是普通引用发生什么情况?如果令occurs是常量引用会发生什么情况?

答:使用引用类型可以避免字符串拷备,因此将s设为引用类型。将s设为常量类型,是由于在该 函数作用域内并不需要对s进行改变,设为常量可避免不必要的对s潜在写操作。 c是字符类型,所占存储空间较少,因此不必将其设为引用类型。 occurs设为引用类型的原因时,希望可以通过它来返回不在return语句内的信息。而它在在函数 作用域内可能会改变,因此需将其设为普通引用。 若s是普通引用则?方面该函数?无法使用常量字符串实参来进行调用,另?方面也带来了在函数体内可能被改变的风险。 如果将occurs设为常量引用,则?无法用它返回字符c出现的次数。 

 

在类的定义中对于访问说明符出现的位置和次数有限定吗?如果有 是什么?什么样的成员应该定义在public说明符之后,什么样的成员应该定义 在private说明之后?

答:对访问说明符的位置与次数没有限制。 可以被类外访问到的成员定义在public后。 只能被类内访问的成员定义在private后。

使用classstruct时有区别吗?如果有,是什么?

答:有区别,默认访问权限不同,struct中成员的默认访问权限是 publicclass中成员的默认访问权限是private

 

封装是何含义?它有什么用处?

答:在类的定义中,封闭即指其中private的部分隐藏了实现细节。 通过封闭可将功能的使?用与实现相分离,使得系统可以更好地应?用需要的变化

 

在你的Person中,你将那些成员声明成public的?哪些声明成 private的?解释你这样做的原因。 

答:将构造函数, getName(), getAddress()声明为public的。将name与 address声明为private的。 前三种成员函数需被类外调?用,因此需声明为public. 后两个数据成员只准许类内访问,实现封闭,因此需声明为private.

 

友元在什么时候用?请分别列举出使?用友元的利弊。

答:类外需要访问private的成员时需将之设置为本类的友元。 其好处是实现了一定的灵活性,满?足了特定的访问需要。 坏处是突破了类的封闭性。增加了维护难度。

 

什么是类的静态成员?他有何优点?静态成员与普通成员有何区 别? 答:直接与类本?身关联?而不是与每个对象关联的成员是类的静态成员。 使?用静态成员,可以避免各个对象的公共元素被重复定义,当该元素变化 时,也只需在?一个位置进?行修改。适当地使?用静态成员,可以提?高程序开 发的效率和可维护性。 静态成员存在于任何对象之外。普通成员存在于每个对象中。 针对静态成员不可以使?用this指针来进行调用,针对普通成员却可以。

 

C++考点问答题