首页
学习
活动
专区
圈层
工具
发布

五、从C语言到C++(五)

这是通过比较调用时提供的参数与每个重载版本的参数列表来完成的。 编译器会尝试将提供的参数与每个重载版本的参数列表进行匹配。...如果某个重载版本的参数列表与提供的参数完全匹配(即不需要任何类型转换),那么这个版本就是最佳匹配,编译器将调用这个版本的函数。 如果没有找到完全匹配的版本,编译器会尝试找到最接近的匹配。...编译器会考虑所有可能的类型转换,并选择一个“最佳”的匹配。 如果存在多个同样“好”的匹配(例如,两个函数都需要相同的类型转换),编译器就会报错,因为这种情况下无法确定应该调用哪个函数。...它只是允许你使用相同的函数名来定义多个具有不同参数列表的函数。在编译时,编译器会根据提供的参数来确定应该调用哪个版本的函数。在运行时,函数重载对程序的行为没有任何影响。 2....与其他特性的关系: 默认参数可以与函数重载结合使用,以增加函数的多样性。 内联函数也可以使用默认参数,但内联函数的主要目的是提高程序性能,而默认参数则主要用于提高函数的灵活性。

55610

C++ 学习笔记

a : b; } 1.5 函数模板重载 1.一个非模板函数可以和同名的函数模板共存,并且函数模板可实例化为和非模板函数具有相同类型参数的函数。函数调用时,若匹配度相同,将优先调用非模板函数。...但若显式指定模板列表,则优先调用函数模板。 2.函数模板不可以进行类型自动转换,非模板函数可以。...9.2 模板和 inline 函数模板全特化后和普通函数相同,但函数模板一般定义在头文件中,为了避免在多个模块 include 时出现重复定义的错误,一般将全特化后的函数模板定义为 inline。...类型转换时T被推导为int[20] } 15.4 初始化列表 1.模板实参如果是初始化列表时,无法直接完成模板参数类型 T 的推导。...0) std::endl; // 都匹配,但第二个更特殊,优先选用 calls fT>(T*) } 如上所示,main 中实例化后的前两个函数完全相同,但是可以同时存在,原因是它们具有不同的签名

7.4K63
  • 您找到你想要的搜索结果了吗?
    是的
    没有找到

    【C++初阶路】--- 模板初阶

    ,因为在编译期间,当编译器看到该实例化时,需要推演其实参类型 通过实a1将T推演为int,通过实参b1将T推演为double类型,但模板参数列表中只有一个T, 编译器无法确定此处到底该将T确定为int...T 为 double 如果类型不匹配,编译器会尝试进行隐式类型转换,如果无法转换成功编译器将会报错。...; } void Test() { Add(1, 2); // 与非模板函数匹配,编译器不需要特化 Addint>(1, 2); // 调用编译器特化的Add版本 } 对于非模板函数和同名函数模板...,如果其他条件都相同,在调动时会优先调用非模板函数而不会从该模板产生出一个实例。...如果模板可以产生一个具有更好匹配的函数, 那么将选择模板; // 专门处理int的加法函数 int Add(int left, int right) { return left + right; }

    17610

    《C++Primer》第十六章 模板与泛型编程

    函数模板 模板定义以关键字template关键字开始,后面跟着一个模板参数列表(不能为空): template T> int compare(const T &v1, const T...如果实参是一个左值,则推断出模板实参类型将是一个左值引用,且函数参数将被实例化为一个(普通)左值引用参数(T&) 这两个规则暗示我们将任意类型的实参传递给T&&类型的函数参数,对于这种类型的参数,(...与之前一样,名字相同的函数必须具有不同数量或类型的参数。 1. 编写重载模板 我们构造一组调试函数命名为debug_rep,每个函数返回一个给定对象的string 表示。...多个可行模板 当多个重载模板对一个调用提供同样好的匹配时,应选择最特例化的版本。 3. 非模板和模板重载 对于一个调用,如果一个非函数模板与一个函数模板提供同样好的匹配,则选择非模板版本。 4....缺少声明可能导致程序行为异常 通常如果使用了一个忘记声明的函数,代码将编译失败。但是对于重载函数模板的函数而言,如果编译器可以从模板实例化出与调用匹配的版本,则缺少的声明就不会报错。

    2.2K10

    Lambda表达式用法超详细整理!!!

    Lambda我们可以将其理解为一个未命名的内联函数。 与任何函数类似,一个lambda具有一个返回类型,一个参数列表和一个函数体。 但与函数不同,lambda可能定义在函数内部。...必须使用尾置返回来指定返回类型 我们可以忽略参数列表和返回类型,但必须永远包含捕获列表和函数体 auto f=[]{return 42;};//分号不能丢 此例中,我们定义了一个可调用对象f,它不接受参数...lambda的调用方式与普通函数调用方式相同,都是使用调用运算符: cout<<f()<<endl;//打印42 在lambda中忽略括号和参数列表等价于指定一个空参数列表。...通常,实参和形参的类型必须匹配。但与普通函数不同,lambda不能有默认参数。 因此,一个lambda调用的实参数目永远与形参数目相等。...,但其函数体中还是使用了两个名字:s和cout,前者是它自己的参数。

    1.1K30

    第 13 章 拷贝控制

    直接初始化时,实际上是编译器使用普通的函数匹配来选择与我们提供的参数最匹配的构造函数。而拷贝初始化是将右侧运算对象拷贝到正在创建的对象中,需要的话还会进行类型转换。...可以对任何函数指定 =delete,对于非拷贝控制成员,也可以引导函数的匹配过程。 析构函数不能定义为 =delete。...移动构造函数,第一个参数是该类类型的一个右值引用,而其他额外参数都必须有默认实参。移动构造函数不分配任何新内存,接管对象的内存。...否则,这些成员默认地被定义为删除的。 左值参数只能调用拷贝操作,右值参数会优先调用移动操作(精确匹配,而拷贝操作往往需要进行一次到 const的转换)。...Foo someMen() & const; // 错误,const限定符必须在前 Foo otherMen() const &; // 正确 }; 如果定义两个或两个以上具有相同名字和相同参数列表的成员函数

    1.2K50

    《C++Primer》第十三章 拷贝控制

    拷贝、赋值与销毁 1. 拷贝构造函数 如果一个构造函数的第一个参数是自身类类型的引用,且任何额外参数都有默认值,则此构造函数是拷贝构造。...(100, '9'); 当使用直接初始化时,我们实际上是要求编译器使用普通的函数匹配来选择与我们提供的参数最匹配的构造函数。...参数和返回值 在函数调用过程中,具有非引用类型的参数要进行拷贝初始化 当一个函数具有非引用的返回类型时,返回值会被用来初始化调用方的结果 拷贝构造函数被用来初始化非引用类类型参数,这一特性解释了为什么拷贝构造函数自己的参数必须是引用类型...&) = delete; // 阻止赋值 ~Nocopy() = default; // 合成的析构函数 // 其他成员 }; 6.2 析构函数不能是删除的成员 如果析构函数被删除,那么无法销毁此类型的对象...这种允许移动的成员函数通常使用与拷贝/移动构造函数和赋值运算符相同的参数模式——一个版本接受指向const的左值引用,另一个版本接受一个指向非const的右值引用。

    1.8K40

    C++从入门到精通——模板

    /* 该语句不能通过编译,因为在编译期间,当编译器看到该实例化时,需要推演其实参类型 通过实参a1将T推演为int,通过实参d1将T推演为double类型,但模板参数列表中只有一个T, 编译器无法确定此处到底该将...我们也可以使用auto做返回值来推,系统会自动匹配最优的 示例 对于这个函数,func(1)直接调用会出错,因为系统不能推出T的类型是什么,这时候我们必须使用显试实例化 auto做模板函数的返回值...() { Add(1, 2); // 与非模板函数匹配,编译器不需要特化 Addint>(1, 2); // 调用编译器特化的Add版本 } 对于非模板函数和同名函数模板,如果其他条件都相同,在调动时会优先调用非模板函数而不会从该模板产生出一个实例...如果模板可以产生一个具有更好匹配的函数, 那么将选择模板 // 专门处理int的加法函数 int Add(int left, int right) { return left + right; } /...// Vector类名,Vectorint>才是类型 Vectorint> s1; Vector s2;

    29710

    第 16 章 模板与泛型编程

    ) : data(make_sharedvectorT>>(b, e)) {} 模板被使用时才会进行实例化,这意味着,当两个或多个独立编译的源文件使用了相同的模板,并提供了相同的模板参数时,每个文件中就都会有该模板的一个实例...对于这种参数,对实参进行正常的类型转换。 当函数返回类型与参数列表中任何类型都不相同时,编译器无法推断出模板实参的类型或者希望允许用户控制模板实例化,可以指定显式模板实参。...T2>(t2), std::forwardT1>(t1) ); } ---- 16.3 重载与模板 函数模板可以被另一个模板或一个普通非函数模板重载,与往常一样,名字相同的函数,必须具有不同数量或类型的参数...与往常一样,如果恰有一个函数提供比任何其他函数都更好的匹配,则选择此函数。但是如果有多个函数提供同样好的匹配,则: 如果同样好的函数中只有一个是非模板函数,则选择此函数。....)); // 错误,此调用无匹配函数 return os; } 可变参数函数通常将它们的参数转发给其他函数,这种函数具有与容器中的 emplace_back函数一样的形式

    1.7K20

    【C++】vector的模拟实现(SGI版本)

    对于size_t和常引用作为参数的构造来说,它的匹配优先级对于10个1实际不是最高的,因为常引用需要进行类模板参数T类型的推导,而10又是整型int,int到size_t还需要进行隐式类型转换,代价有点大...而对于迭代器区间作为参数的构造来讲,函数模板参数InputIterator只需要进行一次类型推导即可完成匹配,所以用10个1来构造时,实际匹配的构造函数是迭代器区间作为参数的构造函数,而在匹配的构造函数中...对于这种问题的解决,可以将size_t换成int类型,或者将10强转为size_t类型,但stl源码的解决方式并非是这样的,而是利用了函数重载来解决了这个问题,多重载了一个类型为int的构造函数。...//所以可以将构造函数的第一个参数类型改为int,但库在实现的时候,默认用的就是size_t,我们改成int就不太好。 //那该怎么办呢?答案就是看源代码。利用重载构造解决问题。...因为对于地址这样的常量不能作为变量进行传递,无法从int*转换为int*& //2.所以在insert之后不要继续使用it,因为他很有可能失效,就算在vs上不失效,但你能保证在其他平台下也不失效吗?

    69830

    C++11列表初始化:从入门到精通

    兼容各种构造函数如果类型定义了接收 std::initializer_list 参数的构造函数,列表初始化会自动匹配并调用此构造函数,使初始化更加灵活和方便。...如果没有适合的 std::initializer_list 构造函数,编译器会尝试使用其他匹配的构造函数。...例如:非聚合类型且无适当构造函数的类:如果一个类不是聚合类型(即具有私有或受保护的成员、基类、虚函数等),同时也没有定义接收 std::initializer_list 或其他形式参数的构造函数,则无法通过列表初始化进行初始化...例如:复杂构造逻辑的类型:对于需要执行逻辑或多个参数的构造函数,如果未定义接收 std::initializer_list 的构造函数,可能无法使用列表初始化,因为列表提供确保正确匹配构造函数的参数。...它提供了一种方便的方式来处理和传递一组相同类型的值,类似于其他语言中的列表或数组。

    22400

    第 16 章 模板与泛型编程

    ) : data(make_sharedvectorT>>(b, e)) {} 模板被使用时才会进行实例化,这意味着,当两个或多个独立编译的源文件使用了相同的模板,并提供了相同的模板参数时,每个文件中就都会有该模板的一个实例...对于这种参数,对实参进行正常的类型转换。 当函数返回类型与参数列表中任何类型都不相同时,编译器无法推断出模板实参的类型或者希望允许用户控制模板实例化,可以指定显式模板实参。...T2>(t2), std::forwardT1>(t1) ); } ---- 16.3 重载与模板 函数模板可以被另一个模板或一个普通非函数模板重载,与往常一样,名字相同的函数,必须具有不同数量或类型的参数...与往常一样,如果恰有一个函数提供比任何其他函数都更好的匹配,则选择此函数。但是如果有多个函数提供同样好的匹配,则: 如果同样好的函数中只有一个是非模板函数,则选择此函数。....)); // 错误,此调用无匹配函数 return os; } 可变参数函数通常将它们的参数转发给其他函数,这种函数具有与容器中的 emplace_back函数一样的形式

    1.7K60

    C++11特性大杂烩

    因为这个迭代器类型由一个类模板来定义,在该类模板未被实例化之前编译器是无法识别这个类型最好也增加一个用initializer_list为参数的赋值运算符重载函数,来支持对列表对象进行赋值。...(老旧的编译器会进行两次拷贝构造),针对内置类型消耗还算小,但针对自定义类型或者容器类参数比如vectorvector vector > >>这种,消耗非常大,不推荐这样用。...,那么PerfectForward的参数t类型是int&图片由于PerfectForward函数用的是万能引用,意味着通过PerfectForward函数按照传入参数的类型匹配调用相同类型的Func函数...必须写(parameters):参数列表。与普通函数的参数列表一致,如果不需要参数传递,则可以连同()一起省略。...,但是报错了,原因是此时的捕捉列表捕捉的是父作用域变量值的拷贝,具有常性无法改变且lambda函数总是一个const函数,可以在参数列表后加mutable表示取消参数的常性添加mutable后运行,通过打印查看参数

    1.1K50

    C++11知识点总结(全面解析C++11经常考到的知识点)

    int array1[] = {1,2,3,4,5}; int array2[5] = {0}; 对于一些自定义的类型,却无法使用这样的初始化。...vectorint> v{1,2,3,4,5};//C++98无法编译 就无法通过编译,导致每次定义vector时,都需要先把vector定义出来,然后使用循环对其赋初始值,非常不方便。...注意: 移动构造函数的参数千万不能设置成const类型的右值引用,因为资源无法转移而导致移动语义失效。...C++11中,std::move()函数位于 头文件中,该函数名字具有迷惑性,它并不搬移任何东西,唯一的功能就是将一个左值强制转化为右值引用,然后实现移动语义。...这样做是为了保留在其他函数针对转发而来的参数的左右值属性进行不同处理(比如参数为左值时实施拷贝语义;参数为右值时实施移动语义) void Fun(int &x){ cout << "lvalue ref

    2.3K10

    C++模板编程:深入理解分离编译的挑战与解决方案

    1.2 非类型模板参数的语法 非类型模板参数在模板声明中通过关键字class(或typename,对于类型模板参数)之外的其他类型来指定。...完全特化: 完全特化是指为模板指定所有模板参数的具体类型或值,从而提供一个完全定制的实现。当模板实例化时,如果提供的参数与某个完全特化的参数完全匹配,则使用该特化的实现。...特化不能改变模板的接口:特化版本必须提供与一般化版本相同的成员函数和接口,否则会导致编译错误。 特化不能增加新的模板参数:特化版本不能增加新的模板参数,它必须匹配一般化版本中的参数数量。...3.1 函数模板的全特化(通过重载实现) 虽然C++语法上不支持函数模板的全特化,但我们可以通过函数重载来达到类似的效果。这意味着为特定的类型提供一个新的、具有相同名称的函数定义。...enable_if_t和std::is_pointer_v来禁用泛型函数模板对于指针类型的实例化。

    65010

    【C++11】C++11新纪元:深入探索右值引用与移动语义

    列表初始化时,必须要跟对应的构造函数参数个数匹配,Data中只能有三个参数,但是vector的参数可以有很多个,列表初始化也支持隐式类型转换 vector vd = { {2024, 7...initializer_list 是一个轻量级的模板类,它用于表示一个给定类型的值的数组,但大小是固定的,且生命周期与包含它的对象相同 initializer_list介绍文档 代码示例 (C++)...int&& r1 = 10; // error C2440: “初始化”: 无法从“int”转换为“int &&” // message : 无法将左值绑定到右值引用 int a = 10;...,因为编译器会选择最匹配的参数调用。...)是C++11及以后版本中引入的一个特性,它允许函数模板以完全相同的类型(包括const限定符和引用类型)转发其参数到另一个函数或模板。

    31310

    【泛型编程】模板全详解

    ,如果其他条件都相同,在调用时会优先调用非模板函数,而不会从该模板生成一个实例。...如果模板可以产生一个具有更好匹配的函数,那么将选择模板。...,不需要函数模板实例化 Add(1, 2.0); // 模板函数可以生成更加匹配的版本,编译器根据实参生成更加匹配的Add函数 } 模板函数不允许自动类型转换,但普通函数可以进行自动类型转换 总结:...调用时候,若几个参数都有符合,则优先匹配类型最合适的。 Ⅲ. 类模板 1....这里要拿 StackT> 去指定类域才对。 ② 类模板中的函数在类外定义,没加 “模板参数列表” ,编译器不认识这个 T 。类模板中函数放在类外进行定义时,需要加模板参数列表。

    86120

    标准库容器

    在尾部之外的位置插入或删除元素可能很慢 array 固定大小数组,支持快速随机访问,不能添加或删除元素 string 与vector相似的容器,但专门用于保存字符。随机访问块。...a和b必须是相同的类型(它们必须是相同的容器类型,且保存的是相同的元素类型),对于array我们还要定义它的大小 C a{b,c,d,e,f,…}C a={b,c,d,e,f,…} a初始化为初始化列表中元素的拷贝...返回新添加的第一个元素的迭代器,若列表为空,则返回p_iterator 向一个vector、string或deque中插入元素会使所有指向容器的迭代器、引用和指针失效 记住,insert函数将元素插入到迭代器所指定的位置之前...,我们将元素类型的对象传递给它们,这些对象被拷贝到容器中 当调用一个emplace函数时,则是将参数传递给元素类型的构造函数。...传递给emplace函数的参数必须与元素类型的构造函数相匹配 #include #includevector> using namespace std; class student

    80330

    【C++】泛型编程:吃透模板

    如果其他条件都相同,在调用时会优先调用非模板函数,而不会从该模板生成一个实例。...如果模板可以产生一个具有更好匹配的函数,那么将选择模板。...,不需要函数模板实例化 Add(1, 2.0); // 模板函数可以生成更加匹配的版本,编译器根据实参生成更加匹配的Add函数 } 模板函数不允许自动类型转换,但普通函数可以进行自动类型转换 总结:...调用时候,若几个参数都有符合,则 优先匹配类型最合适的。 Ⅲ....这里要拿 StackT> 去指定类域才对。 ② 类模板中的函数在类外定义,没加 “模板参数列表” ,编译器不认识这个 T 。类模板中函数放在类外进行定义时,需要加模板参数列表。

    41010

    【c++11】c++11新特性(上)(列表初始化、右值引用和移动语义、类的新默认成员函数、lambda表达式)

    完美转发 如果我们给万能引用函数传入右值,由于右值引用变量本身是左值,所以如果用这个右值引用在内部嵌套调用其他函数,就无法保持参数的属性(传入的其实为左值),从而无法达到预期效果。...若返回值类型已写,那么就算没有参数,参数列表的“( )”也不能省略。 5. 函数体的“{ }”不能省略。...lambda表达式中的参数列表、返回值类型与函数体都很好理解(与普通函数的含义相同),但是这里的捕捉列表是什么呢? 1....捕捉列表 就像函数一样,lambda表达式的函数体只能使用其对应参数列表中的变量,无法使用到外部变量。而捕捉列表可以让我们在lambda表达式的函数体当中使用外层变量。...捕捉列表的其他要点 1. 全局变量和静态变量不能捕捉,也没必要捕捉,可以直接使用。 2. 对于传值捕捉,其本质是将外层数据进行拷贝,并加上const进行修饰,所以函数体内部没办法修改它。

    36710
    领券