每日十问9c+±内存模型和名称空间
1.对于下面的情况,应使用哪种存储方案? a.homer 是函数的形参。
b. secret变量由两个文件共享。
c.topsecret 变量由一个文件中的所有函数共享,但对于其他文件来说是隐藏的。 d. beencalled 记录包含它的函数被调用的次数。习题解析:
a.函数的形参是自动变量的形式,因此 homer 变量的存储方案是自动存储。
b.若多个文件共享一个变量,应当在一个文件内将其定义为外部变量,其存储形式是静态外部链接。在其他需要使用 secret 变量的文件中使用 extern 关键字声明。
c.若 topsecret变量在一个文件内共享且不能被其他文件访问,应当使用内部链接的静态变量,或者可以在未命名的名称空间中进行定义。
d.函数的函数体内定义的变量通常为自动变量,为了保存函数被调用次数,beencalled需要使用本地静态变量来实现这个功能。
2.using 声明和 using 编译指令之间有何区别?
解析:
using 声明可以单独使用名称空间中某个特定的名称,其作用域与 using 所在的声明区域相同。using 编译指令使名称空间中的所有名称可用。如果在全局中使用 using 编译指令,将使该名称空间中的名称在全局可用;如果在函数定义中使用 using 编译指令,将会在该函数中使该名称空间可用。此外,在名称冲突时,两者也会有部分差异,例如,名称空间和 using 声明的区域存在相同的名称,如果在该区域中使用 using 声明导入名称,则两个名称会发生冲突而出错。另外,如果使用 using 编译指令,则该区域的局部版本名称将会隐藏名称空间的版本。因此很多情况下认为 using 声明只导入需要的部分名称,它在使用上比 using编译指令要更安全。
3.重新编写下面的代码,避免使用 using 声明和 using 编译指令。
#include using namespace std; int main(){
double x;
cout<<“Enter value:”: while(!(cin>>x)){
cout<<“Bad input.Please enter a number:” cin.clear();
while(cin.get()!=‘\n’)
continue;
cout<<“Value=”<<x<<end1; return 0;
解析:
题目给定的程序代码中主要使用了 std 名称空间中的内容,如果不使用 using 声明和编译指令,那么可以直接在 std 内的名称前添加作用域运算符 std::。这里主要使用的名称包括 cin、cout、endl,因此修改后的代码如下。
#include int main(){
double x;
std::cout<<“Enter value:”; while(!(std::cin>>x)){
std::cout<<“Bad input.Please enter a number:”; std::cin.clear();
while(std::cin.get()!=‘\n’)
continue;
std::cout<<“Value=”<<x<<std::endl; return 0;
}
4.重新编写下面的代码,使之使用 using 声明,而不是 using 编译指令。
#include using namespace std;
int main()l
double x;
cout<<“Enter value:”; while(!(cin>>x)){
cout<<“Bad input.Please enter an umber:”; cin.clear();
while(cin.get()!=‘\n’)
continue;
cout<<“Value=”<<x<<endl;
解析:
为了使用 using 声明替代 using 编译指令,需要查询当前函数或者文件使用了哪些名称,并依次声明,本程序主要使用了 cin、cout、endl 这3个名字,因此要使用以下 using 声明。
using std::cout;
using std::cin;
using std::endl;
完整代码如下。
#include int main(){
using std::cout;
using std::cin; using std::endl;
double x;
cout<<“Enter value:”;
while(!(cin>>x)){
cout<<“Bad input.Please enter a number:”; cin.clear();
while(cin.get()!=‘\n’)
continue;
cout<<“Value=”<<x<<endl;
}
5.在一个文件中调用 average(3,6)函数时,它返回两个int型参数的 int 型平均值;在同一个程序的另一个文件中调用时,它返回两个 int 型参数的 double 型平均值。应如何实现?
解析:
在同一个程序的不同文件中使用不同函数,且由于两个 average()函数的参数相同(即特征标相同),因此不能重载函数。解决方案是定义不同的名称空间,调用时使用作用域解析;或者在每个文件中包含单独的静态函数定义,限制其是内部链接函数。
6.下面的程序由两个文件组成,该程序显示什么内容?
//filel.cpp
#include
using namespace std; void other(); void another(); int x=10; int y;
int main(){
cout<<x<<endl;{
int x=4;
cout<<x<<end1; cout<<y<<endl;
other(); another();
return 0; 208有这个bau juop
:bie pnisu
void other(){ aiai:bte painu
int y=1;
cout<<“Other:”<<x<<“,”<<y<<endl;
//file2.cpp
()nien anl
#include using namespace std; extern int x; namespace{
int y=-4;}
void another(){
cout<<“another () :”<<x<<“,”<<y<<endl;
}
解析:
为了分析该程序的输出,首先查看 main ()函数内的语句。
cout<<x<<endl;语句输出本文件内外部链接的静态变量 x,所以程序会输出10。
接下来的3条语句在一个单独的语句块内,该语句块中定义的x隐藏了外部链接的x,因此赋值后输出 4,y值未被隐藏,这时使用外部链接的静态变量y,输出结果是初始化结果 0。
other();语句调用文件内的函数other(),该函数内部定义的局部变量隐藏了外部变量 y,但x依然使用外部变量 x,输出结果为:other:10,1。
another();语句调用外部文件中的函数 another(),该函数在 file2.cpp 中,该文件使用了 filel.cpp 中的x变量,但是在文件的名称空间中定义了y=-4,因此 other()函数的x为filel.cpp 内外部链接的x变量,y为 file2.cpp 内无链接的变量y,输出结果为another():10-4。
所以最终显示如下内容。
10
4
0
Other:10,1
another():10-4
7.下面的代码将显示什么内容?#include
using namespace std;
void other();
namespace n1
{
int x=1;
}
namespace n2
{
int x=2;
}
int main(){
using namespace nl;
cout<<x<<endl;
(
int x=4;
cout<<x<<", “<<n1: :x<<”, "<<n2: :x<<endl;
}
using n2::x;
cout<<x<<endl; other();
return 0;
}
void other(){
using namespace n2;
cout<<x<<endl;
{
int x=4;
cout<<x<<“,”<<n1::x<<“,”<<n2::x<<endl;
}
using n2::x;
cout<<x<<endl;
}
解析:
为了分析该程序的输出,首先查看 main()函数内的语句。
● using namespace nl;
cout<<x<<endl;
在main()函数的前两条语句中,声明了名称空间n1,因此第2条语句的输出x为n1
内定义的 x,所以输出 1。
{
int x=4;
cout<<x<<“, “<<n1::x<<”,”<<n2::x<<endl; }
以上语句首先定义了一个语句块,块内定义的变量x会隐藏其他名称空间中的同名变量,cout 输出语句中,通过作用域运算符指定的名称空间不会被块内的局部变量隐藏。因此输出 4,1,2。
using n2::x; cout<<x<<endl;
以上两条语句首先通过 using 声明使用 n2 内的名称,因此 cou 输出 2。
other( );
以上语句调用函数 other()。函数内声明了名称空间 n2,因此首先输出2。
在函数内的语句块中,再次造成名称的隐藏,因此输出局部变量x和作用域运算符修饰的 x,即输出4,1,2。
函数最后再次使用 usingn2::x,上一个语句块内局部变量的生命周期结束,不会造成名称的冲突或隐藏,因此输出 2。
最终程序输出以下结果。
1
4,1,2
2
2
4,1,2
2