传递地址时普通函数与函数模板的语法限制差异解析
问题解析:普通函数与函数模板的参数匹配差异
一、普通函数f传入指针报错的原因
普通函数f的参数被固定声明为const Widget&,这意味着它只能接受可以隐式转换为const Widget&的类型。当传入&arg[0]时,实参的类型是Widget*(指向Widget对象的指针),指针类型和引用类型之间不存在合法的隐式转换规则,编译器无法将Widget*绑定到const Widget&参数上,因此直接触发编译错误。
二、函数模板f2适配两种参数的原因
函数模板f2依靠C++的模板参数推导机制工作:编译器会根据传入的实参类型,自动推导模板参数T的具体类型,然后生成对应的实例化函数,不需要手动指定类型。这让模板函数能灵活适配多种不同的参数类型。
三、两种有效调用场景下的T类型
- 调用
f2(arg[0])时:
实参arg[0]是Widget类型(vector的operator[]返回容器元素的引用),编译器推导T为Widget,生成的函数签名为void f2(const Widget& param),此时调用我们为Widget类自定义的operator<<,输出对象的属性内容。 - 调用
f2(&arg[0])时:
实参是Widget*类型(指向第一个Widget对象的指针),编译器推导T为Widget*,生成的函数签名为void f2(Widget* const & param)(即指向Widget的const指针的引用)。此时打印param时,会调用C++标准库为指针类型提供的默认operator<<,输出指针的内存地址(如示例中的0x55feee619eb0)。
代码示例
#include <iostream> #include <vector> class Widget { public: friend std::ostream &operator<<( std::ostream &output, const Widget &w ) { output << "Attr : " << w.attr; return output; } private: int attr = 5; }; void f(const Widget& param) { std::cout << param << std::endl; } template<typename T> void f2(const T& param) { std::cout << param << std::endl; } int main() { std::vector<Widget> arg = {Widget()}; if (!arg.empty()) { f(arg[0]); //f(&arg[0]); <-- 此处会触发编译错误 f2(arg[0]); f2(&arg[0]); // <-- 为何此处可正常运行? } }
运行输出
Attr : 5 Attr : 5 0x55feee619eb0
内容的提问来源于stack exchange,提问作者RCal
相关产品推荐
相关产品推荐

