带/不带指针的函数原型使用区别
Posted
技术标签:
【中文标题】带/不带指针的函数原型使用区别【英文标题】:Difference in the usage of function prototype with / without pointers 【发布时间】:2020-08-24 23:35:54 【问题描述】:我正在学习简单的 C++ 教程。
#include <iostream>
using namespace std;
int main()
int a = 1, b = 2;
cout << "Before swapping " << endl;
cout << "a = " << a << endl;
cout << "b = " << b << endl;
swap(a,b);
cout << endl;
cout << "After swapping " << endl;
cout << "a = " << a << endl;
cout << "b = " << b << endl;
return 0;
void swap(int &n1, int &n2)
int temp;
temp = n1;
n1 = n2;
n2 = temp;
上面的代码可以正常工作(g++ 和 icc),但是如果我在函数中使用指针,如果我没有在程序开头包含原型,代码就会失败。
#include <iostream>
using namespace std;
void swap(int*, int*); // The code fails if I comment this line.
int main()
int a = 1, b = 2;
cout << "Before swapping" << endl;
cout << "a = " << a << endl;
cout << "b = " << b << endl;
swap(&a, &b);
cout << endl;
cout << "After swapping" << endl;
cout << "a = " << a << endl;
cout << "b = " << b << endl;
return 0;
void swap(int* n1, int* n2)
int temp;
temp = *n1;
*n1 = *n2;
*n2 = temp;
据我所知,C++编译过程是自上而下的,所以第二段代码似乎更合理,在遇到int main()
之前提供函数的信息。我的问题是,为什么在int main()
之前没有函数知识的情况下,第一个代码也能正常工作?
【问题讨论】:
另见Why is “using namespace std;” considered bad practice? 如果您想要另一个惊喜,请从第一个示例中完全删除swap()
函数。你会发现没有它,代码也能构建和运行。
@MilesBudnek 啊哈!我什至没有想到 std
是问题的原因。谢谢你:)
【参考方案1】:
第一个程序的问题是您实际上并没有调用自己的swap
函数。在文件的顶部,您有:
using namespace std;
这会将std::swap
带入范围,这就是您实际调用的函数。如果您将cout
语句放在您自己的swap
中,您会发现它实际上从未被调用过。或者,如果你在main
之前声明你的swap
,你会得到一个模棱两可的电话。
请注意,此代码并非必需,因为iostream
不一定会将std::swap
带入作用域,在这种情况下,您将收到没有swap
来电。
在第二个程序中,对 swap(&a, &b)
的调用失败,因为没有接受 2 个临时指针的 std::swap
重载。如果您在调用main
之前声明了您的swap
函数,那么它会调用您自己的函数。
您的代码中真正的错误是using namespace std;
。永远不要那样做,你会避免这种性质的问题。
【讨论】:
"将 std::swap 带入范围" ...但可能不是在每个编译器上。仍然建议当您希望使用 std::swap 时,您应该始终#include 适当的标头。您所拥有的可能还包括交换,但不能保证。就在今天,我看到 std::swap() 现在在 3 个标题中:(我期望的地方)、第一个版本有效的原因是它根本不调用您的swap(...)
函数。命名空间 std
提供 - Edit: 取决于您(以及标准标题本身)包含的标题 - swap(...)
各种类型和整数的函数就是其中之一.如果要删除 using namespace std
,则必须键入 std::swap(...)
才能达到相同的效果(std::cout
、std::endl
也是如此)。
这就是为什么using namespace
在我看来对初学者来说是一把双刃剑的原因之一,但这是另一个话题。
【讨论】:
"命名空间std提供了swap(...)函数..."。不,std::namespace 不提供库......库为 std::namsepace 提供了贡献。 std::swap 保证在特定库中提供,但并非所有作为 std::namespace 贡献者的库都会提供 std::swap。例如,cppreference.com 报告说 std::swap() 可以直接从 3 个标头中获取:、您的代码很好;但你是对的,如果你对你指向的行发表评论,它会失败。 但实际上,正如其他人告诉你的那样,c ++中有一个 Swap 函数,所以你创建一个函数的原型然后再做也没关系,因为编译器会调用自己的 swap 函数。
但由于 swap 适用于除指针以外的任何数据类型,那么您就会明白问题的原因,因为在这种情况下,您必须创建自己的 swap 函数来接受指针作为参数。
只需将您的函数移到 main 上方即可使其正常工作,仅此而已:
#include <iostream>
using namespace std;
//void swap(int*, int*); // The code fails if I comment this line.
void swap(int* n1, int* n2)
int temp;
temp = *n1;
*n1 = *n2;
*n2 = temp;
int main()
int a = 1, b = 2;
cout << "Before swapping" << endl;
cout << "a = " << a << endl;
cout << "b = " << b << endl;
swap(&a, &b);
cout << endl;
cout << "After swapping" << endl;
cout << "a = " << a << endl;
cout << "b = " << b << endl;
return 0;
【讨论】:
"因为编译器调用了它自己的交换函数。"不会。编译器将仅搜索列出的包含库(以及它们包含的库,即间接的)。 std::swap 仅在 a) 在您的代码中使用(引用),并且 b) 在包含的库中找到时才链接。如果在您的构建套件中,库以上是关于带/不带指针的函数原型使用区别的主要内容,如果未能解决你的问题,请参考以下文章