modern_cpp_3-C++ Basic Syntax


Lecture 2的Slides: Modern C++ for Computer Vision Lecture 2: C++ Basic Syntax (uni-bonn.de)

该部分主要介绍了C++中的关键词、实体、实体的声明和定义、类型、变量、标识符的命名规则、表达式、if else结构、switch结构、while循环、for循环、算术表达式、条件表达式、自增自减

if(STATEMENT){
	//...
}
else{
	//...
}

switch(STATEMENT){
	case 1: EXPRESIONS;break;
	case 2: EXPRESIONS;break;
}

while(STATEMENT){
	//...
}

for(int i=0;i<10;i++){
	//...
}

Spoiler Alert(补充)

1. c++17中的for循环和Python 3.x中的for循环对比

在最新的C++ 17标准中,for循环的新写法和Python中的写法的对比:

//Pythonic Implementation
my_dict = {'a':27,'b':3}
for key,value in my_dict.items():
	print(key,"has value",value)
// Implementaion in c++ 17
std::map<char,int> my_dict{{'a',27},{'b',3}}
for (const auto&[key,value]:my_dict)
{
    std::cout<<"has value"<<value<<std::endl;
}

可见新标准很有Pythonic taste,但是C++的实现要比Python快15倍:

在这里插入图片描述

2. Built-in types

C++中的"Out of the box"类型(out-of-the-box,即开箱即用的),可以参考Fundamental types - cppreference.com

int a = 10;
auto b = 10.1f ; // Automatic type [float]
auto c = 10; //Automatic type [int]
auto d = 10.0 ; // Automatic type [double]
std::array<int,3> arr={1,2,3}; // Array of intergers

这里的自动类型也有点像Python。

3. C-style strings are evil

C++中可以像C中的其他类型一样,按照C的风格编程:

#include<cstring>
#include<iostream>

int main(){
    const char source[] = "Copy this";
    char dest[5];
    std::cout<<source<<std::endl;
    std::strcpy(dest,source);
    std::cout<<dest<<std::endl;
    //Source is const, no problem right
    std::cout<<source<<std::endl;
    return 0;
}

在这里插入图片描述

你可能以为sourceconst char类型的,并不应该改变,但是结果却出乎意料,这就是所谓的"C-style strings are evil",所以更加推荐使用Strings类型,有这

几点注意事项:

  1. #include<string>之后可以使用std::string
  2. string类型实现了运算符重载,可以使用+进行拼接;
  3. 可以通过str.empty()检查str是否是空的;
  4. 可以和I/O streams结合,玩出花样

例如上面的例子,我们使用C++中的string类型实现:

#include<iostream>
#include<string>

int main(){
    const std::string source{"Copy this"};
    std::string dest = source;
    std::cout << source << '\n';
    std::cout<< dest <<'\n';
    return 0;
}

在这里插入图片描述

这次的运行结果就是完整的表示出来了。

补充:为什么第一个例子中会出现这样的错误呢?我们找到std::strcpy官方说明,该函数的签名是:

char* strcpy( char* dest, const char* src );

Copies the character string pointed to by src, including the null terminator, to the character array whose first element is pointed to by dest.

The behavior is undefined if the dest array is not large enough. The behavior is undefined if the strings overlap.

我们看了一下strcpy的函数原型:

//C语言标准库函数strcpy的一种典型的工业级的最简实现。
//返回值:目标串的地址。
//对于出现异常的情况ANSI-C99标准并未定义,故由实现者决定返回值,通常为NULL。
//参数:des为目标字符串,source为原字符串。

char* strcpy(char* des,const char* source)
{
    char* r=des;
    assert((des != NULL) && (source != NULL));
    while((*r++ = *source++)!='\0');
    return des;
}
//while((*des++=*source++));的解释:赋值表达式返回左操作数,所以在赋值'\0'后,循环停止。

这里其实并不是语言的问题,而是sourcedest都位于栈区,且在内存上相邻,所以dest的内存溢出到source中,覆盖了source的前面部分内容,并加上了\0,两者的位置信息如下所示:

+--------+
...
+--------+
| src[2] |   <--- -0x5
+--------+
| src[1] |   <--- -0x6
+--------+
| src[0] |   <--- -0x7
+--------+
| dest[3]|   <--- -0x8
+--------+
| dest[2]|   <--- -0x9
+--------+
| dest[1]|   <--- -0xa
+--------+
| dest[0]|   <--- -0xb
+--------+

应该如何避免因为dest指向的内存空间不够大造成的缓存溢出(buffer Overflow)呢?

这里官方给出了范例,为了避免因为dest长度不够造成的不可预测的行为,这里根据src的长度调整src的长度:

#include <iostream>
#include <cstring>
#include <memory>
 
int main()
{
    const char* src = "Take the test.";
//  src[0] = 'M'; // can't modify string literal
    auto dst = std::make_unique<char[]>(std::strlen(src)+1); // +1 for the null terminator
    std::strcpy(dst.get(), src);
    dst[0] = 'M';
    std::cout << src << '\n' << dst.get() << '\n';
}

当然也可以使用更加安全的strncpy或者strcpy_s

4. Any variables can be const

值得注意的是,任何类型都能被声明为const类型,只要你确定它不会改变。

Google-Style以驼峰法(CamelCase)命名常量,并以小写字母k开头,例如:

const float kImportantFloat = 20.0f;
const int kSomeInt = 20;
const std::string kHello = "Hello";

补充:Google-Style以蛇形法(snake_case)命名变量,并且全部都是小写字母,例如some_var

变量的引用(reference)也是十分常见的用法,比拷贝数据更快而且代码量更少,但是有时候为了避免不想要的改变,我们会使用const

5. I/O streams

#include<iostream>来使用I/O stream

这里是常用的String streams:

  1. 标准输出cerrcout
  2. 标准输入cin
  3. 文件流fstreamifstreamofstream
  4. 字符串stringstream,既可以将intdoublestring等类型的组合转化为string,也可以将strings分解为intdoublestring等。
6. Program input parameters

C++允许向二进制文件传递参数,例如main函数就可以接收参数:

int main(int argc,cahr const *argv[])

其中,argc表示输入参数的个数,argv是输入字符串的数组,默认前者等于1,后者等于"<binary_path>"

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值