【C++】auto关键字(c++11)

  • 概念

C++11中,auto不再是一个存储类型指示符,而是一个自动推导变量的类型,如:

#include <iostream>
#include <typeinfo>
using namespace std;

int TestAuto()
{
	return 10;
}

int main()
{
	int a = 10;
	auto b = a;//由a是int,可以推导出b的类型是int
	auto c = 'a';//由‘a’推导出c的类型是char
	auto d = TestAuto();
	cout << typeid(b).name() << endl;
	cout << typeid(c).name() << endl;
	cout << typeid(d).name() << endl;

    auto e;//这条语句编译不通过,使用auto定义变量时,必须对其进行初始化
	system("pause");
	return 0;
}
//typeid(b).name()是打印类型名称的函数

运行结果:

需要注意的是:

使用auto定义变量时,必须对其进行初始化,因为auto并非是一种类型的声明,而是一个类型声明时的“占位符”,编译器在编译期间会将auto替换为变量实际的类型。

  • auto使用规则

1.auto与指针和引用结合起来使用。用auto声明指针类型肘,用auto和auto*没有任何区別,但用auto声明引用类型吋必须加&

#include <iostream>
#include <typeinfo>
using namespace std;

int main()
{
	int x = 10;
	auto a = &x;
	auto* b = &x;
	auto& c = x;
	cout << typeid(a).name() << endl;
	cout << typeid(b).name() << endl;
	cout << typeid(c).name() << endl;
	
	system("pause");
	return 0;
}

2.在同一行定义多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际只对第一个类型进行推导,然后用推导出来的类型定义其它变量。

#include <iostream>
using namespace std;

void TestAuto()
{
	auto a = 1, b = 2;
	//auto c = 3, d = 4.0;//错误
	auto c = 3, d = 4;//正确
	cout << c << endl;
	cout << d << endl;
}

int main()
{
	TestAuto();
	
	system("pause");
	return 0;
}
  • auto不能自动推导的场景

1.auto不能作为函数的参数

void TestAuto(auto a)//此处代码不通过,auto不能作为形参类型,因为编译器无法对a的实际类型进行自动推导
{
    ;
}

2.auto不能用来直接声明数组

void TestAuto()
{
	int a[] = { 1, 2, 3 };
	auto b[3] = a;//auto类型不能出现在顶级数组类型中
}

3.为了避免与c++98中的auto发生混淆,c++11中只保留了auto作为类型推导的用法

4.auto最常见的就是会跟c++11中的新式for循环,还有lambda表达式进行配合使用

#include <iostream>
using namespace std;

int main()
{
	int array[] = { 1, 2, 3, 4, 5 };
	for (auto e : array)//依次取array里面的元素读给e
		cout << e << endl;
	
	system("pause");
	return 0;
}

运行结果:

5.auto不能定义类的非静态成员变量

6.实例化模板时不能使用auto作为模板参数

  • 基于范围的新式for循环(c++11)

在C++98中如果要遍历一个数组,可以按照以下方式进行:

void TestFor()
{
intarray[]={1,2,3,4,5};
for (int i = 8; i < sizeof(array) / sizeof(array[0]); ++i )
   array[i] *= 2;

for (int* p = array; p < array + sizeof(array)/ sizeof(array[0]); ++p)
  cout << *p << endl;

}

对于一个有范围的集合而言,由程序员来说明循环的范围是多余的,有时候还会容易犯错误。因此C++11中引入了基于范围的for循环。for循环后的括号由冒号”:”分为两部分:第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围。

 

int main()
{
	int array[] = { 1, 2, 3, 4, 5 };
	for (auto e : array)//依次取array里面的元素读给e
		cout << e << " ";
	
	system("pause");
	return 0;
}

如果此时想要打印array数组元素的2倍时,就必须加引用&:

#include <iostream>
using namespace std;

int main()
{
    int array[] = { 1, 2, 3, 4, 5 };
    for(auto& e : array)//遍历数组,给数组的每个对象*2;
        e = e * 2;

    for (auto& e : array)//遍历数组,依次取出数组里面的元素,赋给e
        cout << e << " ";
    system("pause");
    return 0;
}

分析:不加“&”的意思是取出array里面的每个对象,赋给e,e虽然被改变了,但数组里面的对象并没有变;加“&”表示e是数组里面 每个对象的别名,此时e一改变,数组里面的每个对象也会改变,因为e是每个对象的别名。

注意:与普通循环类似,可以用continue来结束本次循环, 也可以用break来跳出整个循环。

 

  • for的使用条件

1. for循环迭代的范围必须是确定的,对于数组而言,就是数组中第一个元素和最后一个元素的范围;对于类而言,应该提供begin和end的方法,begin和end就是for循环迭代的范围,以下代码就有问题:

void Test(int array[])
{
	for (auto& e : array)
		cout << e <<endl;
}

分析:这个代码编译不通过,此时的array不再是数组而是一个指针,for的范围不确定。

2.for循环要支持迭代器,还得支持++和==。

  • nullptr(c++11)

 

在C/C++编程习惯中,声明一个变量时最好给该变量一个合适的初始值,否则可能会出现不可预料的错误,比如未初始化的指针。如果一个指针没有合法的指向,我们基本都是按照如下方式对其进行初始化:

void TestPtr(){

int* p1 = NULL;int* p2 = 0;

而NULL实际是一个宏, 在传统的C头文件(stddef.h)中,可以看到如下代码:

 

#ifndef NULL
#ifdef_ .cplusplus
#define NULL  0
#else
#define NULL ((void *)0)
#endif
#endif

我们发现NULL在c++中被定义为整形常量0,在c语言中被定义为无类型指针(void* )的常量。这种定义,在使用空值的指针时,都不可避免的会遇到一些麻烦,比如:

#include <iostream>
using namespace std;


void f(int)
{
	cout << "f(int)" << endl;
}
void f(int*)
{
	cout << "f(int*)" << endl;
}
int main()
{
	f(0);//调f(int)
	f(NULL);//调f(int)
	f((int*)NULL);//调f(int*)
	system("pause");
	return 0;
}

运行结果:

这个程序的本意是:想通过f(NULL)调用fint*)函数,但是由于NULL被定义成0,因此与程序的初衷相悖。在C++98中,字面常量0既可以是一个整形数字, 也可以是无类型的指针(Void)常量, 但是编译器默认情况下将其看成是一个整形常量, 如果要将其按照指针方式来使用,必须对其进行强转(void *)0。

  • nullptr

为了考虑兼容性,C++11并没有消除常量0的二义性,而是给出了全新的nullptr,表示空值指针。C++11为什么不在NULL的基础上进行扩展,这是因为NULL以前就是一个宏, 而且不同的编译器厂商对于NULL的实现可能不太相同,而且直接扩展NULL,可能会影响以前旧的程序。因此:为了避免混淆,C++11提供了nullptr,即: nullptr代表- 个指针空值常量。nullptr是有类型的, 其类型为nullptr. _t,仅仅可以被隐式转化为指针类型,nullptr. _t被定义在头文件中:

typedef decltype(nullptr) nullptr_ t;

需要注意的是:

1.在使用nullptr表示指针空值时,不需要包含头文件,因为nullptr是C++11作为新关键字引入的。

2.在C++11中,sizeof(nullptr) 与sizeof(void*)0)所占的字节数相同。

3.为了提高代码的健壮性,建议在后续表示指针空值时,最好使用nullptr。

这里还有常见的一类题:

请区分:NULL、0、'\0'、"\0"?

NULL:是被定义出来的一个宏,它不是关键字,值为0;

0:是整形的0,值为0;

'\0':是字符0,值为0;

"\0":是字符串;

计算:

#include <iostream>
using namespace std;
int main()
{
    char str[] = "\0";
    cout << strlen(str)<< endl;//0字节
    cout << sizeof(str) << endl;//2个字节
    system("pause");
    return 0;
}

其中strlen(str)大小为0,因为转义字符\+0,就是字符串中的结束标志"\0",只要遇到"\0",它就自动停下来了,所以strlen(str)大小为0;sizeof(str)大小为2个字节,转义字符\+0是一个字符,还有字符串结束标志的那个"\0",加起来就是2个字节。

再比如:

#include <iostream>
using namespace std;

int main()
{
    char str[] = "\\0";
    cout << strlen(str)<< endl;//2个字节
    cout << sizeof(str) << endl;//3个字节
    system("pause");
    return 0;
}

这个程序里面strlen(str)大小为2个字节,转义字符\+\转义为\,后面还有个数字0,总共是2个字节;sizeof(str)大小为3个字节。

  • 14
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在MATLAB中实现机械臂的仿真可以使用Robotic System Toolbox来进行。Robotic System Toolbox包含许多工具和函数,可以实现机械臂的建模、控制和仿真。 首先,需要定义机械臂的模型。可以使用robotics.RigidBodyTree类来创建机械臂的刚体树结构。通过添加关节和刚体可以构建机械臂的结构。可以使用函数robotics.RigidBody来创建刚体,并使用函数robotics.Joint来创建关节。 接下来,可以使用robotics.RigidBodyTree类中的函数来定义机械臂的初始状态。可以设置每个关节的初始位置和速度。 然后,可以使用robotics.RigidBodyTree类中的函数来进行机械臂的运动控制。可以使用函数robotics.InverseKinematics来实现逆运动学,根据目标位置和姿态来求解关节角度。可以使用函数robotics.CartesianTrajectory来生成机械臂的轨迹,指定起始和目标位置以及运动时间。 最后,可以使用robotics.RigidBodyTree类中的函数来进行机械臂的仿真。可以使用函数robotics.Rate来指定仿真的频率,然后使用循环来更新机械臂的状态和控制输入,实现机械臂的运动。 以下是一个基本的机械臂仿真的示例代码: ```matlab % 创建机械臂模型 robot = robotics.RigidBodyTree; % 添加机械臂的关节和刚体 % 设置机械臂的初始状态 % 运动控制 % 仿真循环 % 绘制机械臂的运动轨迹 ``` 在实际的机械臂仿真中,可能还需要考虑机械臂的动力学、碰撞检测和路径规划等问题。可以使用Robotic System Toolbox中的其他工具和函数来处理这些问题。
引用中提到,C语言中的auto关键字用于声明变量并自动推断其类型。auto declarator initializer*;的语法表示可以声明一个或多个具有自动类型推断的变量。同时,引用也提到了C语言引入了auto关键字来实现类型推导,通过auto关键字可以方便获取复杂的类型,并简化书写,提高编码效率。 更具体地说,使用auto关键字声明变量时,编译器会根据变量的初始化表达式来推断变量的类型。这样可以减少代码中的类型声明,使代码更加简洁和灵活。例如,在函数参数中使用auto关键字可以实现参数的类型推导,使函数调用更加方便。同时,auto关键字还可以与范围for循环结合使用,自动推断容器中元素的类型。 关于C语言中auto关键字的更多详细信息,可以参考引用所提供的Microsoft的官方文档链接。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [C++ auto关键字](https://blog.csdn.net/L_Chee/article/details/125349312)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [C++基础:关键字auto](https://blog.csdn.net/weixin_58368590/article/details/124871252)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值