当前位置: 首页 > article >正文

自动类型和推导(aotu和decltype)

auto

auto 关键字允许编译器根据变量的初始化值推导出变量的类型。这减少了类型的显式声明,使代码更加简洁和可读。

#include <iostream>  
#include <vector>  

int main() {  
    auto x = 42;               // 推导为 int  
    auto y = 3.14;            // 推导为 double  
    auto str = "Hello, C++";  // 推导为 const char*  

    // 使用 auto 推导容器的类型  
    std::vector<int> vec = {1, 2, 3, 4, 5};  
    for (auto it = vec.begin(); it != vec.end(); ++it) {  
        std::cout << *it << " ";  
    }  
    
    return 0;  
}

优点

  • 简化代码:消除了冗长的类型声明,特别适用于复杂类型(如迭代器)。
  • 增强可读性:减少了程序员的书写负担,使代码更清晰。
  • 适应性强:对于模板和泛型编程特别有用,可以在不明确类型的情况下推导出类型。

注意事项

  • auto 变量必须在声明时进行初始化。不能作为函数参数使用。因为只有在函数调用的时候才会给函数参数传递实参,auto要求必须要给修饰的变量赋值,因此二者矛盾。
int func(auto a, auto b)	// error
{	
    cout << "a: " << a <<", b: " << b << endl;
}
//报错
  • auto 只知道初始化表达式的类型,因此不能用于类型不明确的情况下。
  • 不能使用auto关键字定义数组
int func()
{
    int array[] = {1,2,3,4,5};  // 定义数组
    auto t1 = array;            // ok, t1被推导为 int* 类型
    auto t2[] = array;          // error, auto无法定义数组
    auto t3[] = {1,2,3,4,5};;   // error, auto无法定义数组
}
  • 无法使用auto推导出模板参数
template <typename T>
struct Test{}
 
int func()
{
    Test<double> t;
    Test<auto> t1 = t;           // error, 无法推导出模板类型
    return 0;
}

decltype

在某些情况下,不需要或者不能定义变量,但是希望得到某种类型,这时候就可以使用C++11提供的decltype关键字了,在C++中,decltype 是一个非常有用的操作符,它允许你获取表达式的类型,而不需要先定义该表达式。这为编写灵活和类型安全的代码提供了强大的支持。尤其是在涉及模板和泛型编程时,decltype 可以帮助我们推导出复杂类型。

#include <iostream>  

int main() {  
    int x = 5;  
    decltype(x) y = 10; // y 的类型被推导为 int  

    std::cout << "y = " << y << std::endl; // 输出: y = 10  
    return 0;  
}

用于函数返回类型

#include <iostream>  

int add(int a, int b) {  
    return a + b;  
}  

decltype(add(1, 2)) multiply(int a, int b) { // 根据 add(1, 2) 来推导返回类型  
    return a * b;  
}  

int main() {  
    decltype(add(1, 2)) result = multiply(2, 3); // result 的类型为 int  
    std::cout << "multiply(2, 3) = " << result << std::endl; // 输出: multiply(2, 3) = 6  
    return 0;  
}

与auto结合

#include <iostream>  
#include <vector>  

int main() {  
    std::vector<int> vec = {1, 2, 3};  
    auto it = vec.begin(); // it 是 std::vector<int>::iterator  

    decltype(it) anotherIt = it; // anotherIt 将被推导为 std::vector<int>::iterator  

    for (decltype(vec.size()) i = 0; i < vec.size(); ++i) { // i 的类型为 std::vector<int>::size_type  
        std::cout << vec[i] << " ";  
    }  
    std::cout << std::endl;  

    return 0;  
}

优点

  • 推导变量的类型:使用现有表达式的类型来声明新变量。
  • 结合auto使用:当无法用 auto 推导类型时,可以使用 decltype。
  • 函数返回类型推导:可以在实现中获取某个表达式的返回类型。

注意事项

  • 无副作用:在使用 decltype 时,传递给它的表达式不会被求值。因此,可以使用会导致副作用的表达式(如调用函数)来获得其返回类型,而不会执行该函数。
  • 引用的处理:如果表达式是一个引用,decltype 会保留引用类型。
int a = 10;  
int& ref = a;  
decltype(ref) anotherRef = ref; // anotherRef 也是一个 int&

返回类型后置

在C++中,返回类型后置(trailing return type)是一种语法,用于在函数声明时将返回类型放在参数列表的后面。这种形式特别适合于函数模板、复杂类型或需要使用decltype进行类型推导的情况。返回类型后置语法最早是在C++11中引入的。

语法形式

返回类型后置的语法是使用 -> 符号来标识返回类型,具体形式如下:

auto functionName(parameters) -> returnType {  
    // function body  
}

使用场景

  • 简化模板代码:尤其在涉及复杂的返回类型时,可以减少代码的混乱。
  • 配合 decltype 使用:适合于当返回类型依赖于函数参数时,可以在函数体内确定返回类型。
  • Lambda 表达式:在某些内联函数中,返回类型后置的写法更加简洁明了。

基本示例

#include <iostream>  

auto add(int a, int b) -> int { // 返回类型后置  
    return a + b;  
}  

int main() {  
    std::cout << "Sum: " << add(3, 4) << std::endl; // 输出: Sum: 7  
    return 0;  
}

使用decltype

#include <iostream>  

int multiply(int a, int b) {  
    return a * b;  
}  

auto calculate(int x, int y) -> decltype(multiply(x, y)) { // 返回类型由 multiply 确定  
    return multiply(x, y);  
}  

int main() {  
    std::cout << "Product: " << calculate(5, 6) << std::endl; // 输出: Product: 30  
    return 0;  
}

使用于模板函数

#include <iostream>  
#include <vector>  

template<typename T>  
auto getElement(const std::vector<T>& vec, std::size_t index) -> T {  
    return vec[index]; // 返回类型是模板参数 T  
}  

int main() {  
    std::vector<int> numbers = {1, 2, 3, 4, 5};  
    std::cout << "Element at index 2: " << getElement(numbers, 2) << std::endl; // 输出: Element at index 2: 3  
    return 0;  
}

于lambda表达式结合

#include <iostream>  
#include <vector>  

int main() {  
    std::vector<int> vec = {1, 2, 3, 4, 5};  

    auto lambda = [](int a, int b) -> int { return a + b; }; // 返回类型后置在 Lambda 中  
    std::cout << "Lambda sum: " << lambda(3, 4) << std::endl; // 输出: Lambda sum: 7  

    return 0;  
}

http://www.kler.cn/a/416251.html

相关文章:

  • 【verilog教程】verilog带参数例化
  • HarmonyOS NEXT应用元服务开发Intents Kit(意图框架服务)综述
  • mysql之基本常用的语法
  • 性能监控框架的底层原理
  • Spring Boot教程之十三:更改Spring Boot的默认端口
  • 摄像头原始数据读取——V4L2(userptr模式,V4L2_MEMORY_USERPTR)
  • 【单片机的结构和组成】
  • 深度学习:利用GPU进行训练
  • 牛客练习赛132
  • A-star算法
  • 扩散模型_Diffusion Model
  • 【小白学机器学习35】数据表:整洁数据表,交叉表/列联表,以及两者转化pd.pivot_table()
  • 依赖倒置原则:Java实践篇
  • 【大数据学习 | Spark调优篇】常用的shuffle优化
  • 如何快速上手UPR ---查看资源检测报告
  • 【论文复现】Modnet 人像抠图
  • 24.11.26 神经网络 参数初始化
  • 阿里云CDN:稳定性究竟如何?
  • set up RAGFlow on your Mac
  • VSOMEIP主要流程的时序