| Swift | C++
:-:|:-:|:-:
关键字 | let / var | const auto / auto
作用 | 创建一个常量/变量 | 创建一个常量/** 变量**
关于数值
Swift 中使用 let
来创建常量,使用var
来创建变量.
var myVariable = 42
myVariable = 50
let myConstant = 42
C++ 中可以使用 auto
创建变量, 使用const auto
创建常量(也可以用其他形式创建变量).
#include <iostream>
int main() {
auto myVariable = 42;
myVariable = 50;
const auto myConstant = 42;
return 0;
}
const
是 类型说明符, 用于说明后面那个东西是常量, 初次赋值之后就再也不能改变了.
你不需要指明常量或变量的类型, 在声明和同时赋值的话, 编译器可以自动推断类型.
上面例子中的 myVariable
和 myConstant
:
- Swift 将它们推断为
Int
类型. - C++ 将它们推断为
int
类型.
一个常量或变量的值, 在编译期并不需要明确的值. 但是如果没有提供足够的信息(或者没有初始值), 那么你需要显式的指明类型.
Swift 中可以在变量或常量右面声明类型, 用冒号:
分隔:
var varValue: Int
let implicitInteger = 70
let implicitDouble = 70.0
let explicitDouble: Double = 70
C++中则需要先写类型名,再写变量名(创建常量/变量的另外的形式):
#include <iostream>
int main() {
int varValue;
const int constImplicitInt = 70;
const double constImplicitDouble = 70.0;
return 0;
}
Swift 练习: 创建一个常量,显式指定类型为 Float 并指定初始值为4。
C++ 练习: 创建一个常量,显式指定类型为 float 并指定初始值为4。
关于字符串
Swift 中的值永远不会被隐式转换为其他类型. 如果你需要把一个值转换为其他类型, 请显式转换:
let label = "The width is "
let width = 94
let widthLabel = label + String(width)
删除 String 试试看? 错误提示是什么?
** C++中**的值可以被隐式转换为其他类型, 但并不是所有类型的值都可以. 只有该类型支持隐式转换为其他类型, 才可以把该类型的值隐式转换为其他类型:
#include <iostream>
#include <string> // 创建一个字符串变量,需要先包含 string 头文件
int main() {
int intValue = 70;
double doubleValue = intValue;
std::string aCplusplusString = "a C string"; // std::string 表示使用在标准库 std 中的 string 类型
return 0;
}
把
std::string aCplusplusString = "a C string";
写成std::string aCplusplusString = doubleValue;
试试?
错误提示是什么?
Swift 中有一种把值转换成字符串的更简单的方法: 把值写到括号中,然后在括号前写一个反斜杠. 形如: "字符串内容\(值)字符串其他内容"
let apples = 3
let oranges = 5
let appleSummary = "I have \(apples) apples."
let fruitSummary = "I have \(apples + oranges) pieces of fruit."
** C++中**这种数值向字符串的转换是由标准库函数 to_string
来完成的:
#include <iostream>
#include <string> // 创建一个字符串变量,需要先包含 string 头文件
int main() {
int intValue = 70;
double doubleValue = intValue;
std::string aCplusplusString = "a C string"; // std::string 表示使用在标准库 std 中的 string 类型
auto otherString = std::to_string(doubleValue); // std::to_string 表示使用在标准库 std 中的 to_string 函数
auto otherString2 = std::to_string(doubleValue + intValue);
return 0;
}
Swift练习:使用 \( )来把一个浮点数转换成字符串, 并加上某人的名字
C++练习:使用标准库中的 to_string 函数来把浮点数转换成字符串
关于数组与集合
** Swift 中**可以使用方括号[ ]
来创建数组或字典, 并使用下标或者键来访问元素. 最后一个元素后面允许有逗号.
var shoppingList = ["catfish", "water", "tulips", "blue paint"]
shoppingList[1] = "bottle of water"
var occupations = [
"Malcolm": "Captain",
"Kaylee": "Mechanic",
]
occupations["Jayne"] = "Public Relations"
// 创建空数组或字典,可以使用初始化语法.
let emptyArray = [String]()
let emptyDictionary = [String: Float]()
// 如果类型信息可以推断出来, 可以使用[]创建空数组,使用[:]创建空字典.
// 当你为一个变量设置新值或者给一个函数传递参数的时候就可以这样做
shoppingList = []
occupations = [:]
** C++中**创建向量或关联数组, 则需要先指明类型名, 然后在<>
中指定元素的类型, 再写变量名, 然后给变量初始化或赋值. 初始化或赋值时, 最后一个元素后面也允许有逗号. 只是没有Swift这么简洁了:
#include <iostream>
// 注意, 在 C++ 中, 下面这些东西统称为容器.
#include <string> // 包含 string 来创建C++字符串
#include <vector> // 包含 vector 来创建向量(类似数组), 另外也可以包含 array 来创建C++数组, 当然什么也不包含, 直接创建 C 数组
#include <map> // 包含 map 来创建有序的不重复关联数组. 另外也可以包含 unordered_map、 multimap、 unordered_map_multimap来分别创建无序的不重复的关联数组、有序的可重复的关联数组、 无序的可重复的关联数组
int main() {
// 在创建的时候就不能使用 auto 进行类型推断了, 需要先指明类型, 再写变量名
std::string aCArray[4] = {"catfish", "water", "tulips", "blue paint"}; // 创建 C 数组
aCArray[1] = "bottle of water";
// 创建 vector 需要在<>中指明 vector 中包含元素的类型
std::vector<std::string> aVector = {"catfish", "water", "tulips", "blue paint"};
aVector[1] = "bottle of water";
// 创建 map 需要在<>中分别指明 map 键和值的类型
std::map<std::string, std::string> aMap = {
{"Malcolm", "Captain"},
{"Kaylee", "Mechanic"},
}; // std::map<std::string, std::string> 表示使用 std 标准库中的无序的关联数组, 其中键值的类型分别使用标准库 std 中的 string
aMap["Jayne"] = "Public Relations";
// 创建空向量/数组以及空字典
std::vector<std::string> aEmptyArray;
std::map<std::string, std::string> aEmptyMap;
// 现在可以使用 auto 了
auto aCArray2 = aCArray;
auto aMap2 = aMap;
return 0;
}
解释
-
命名空间
-
C++中的命名空间是为了防止名字冲突, 给防止名字冲突提供了更加可控的机制.
代码std::string
, 其中::
是作用域运算符,::
运算符把它的左右两边符号组合在一起, 表示使用在它的左边符号所代表的命名空间中(std
), 找到的它的右边符号string
; 也就是说std::string
表示使用存在在std
中的string
如果::
的左边什么都没有, 如::something
表示使用在全局作用域中的something
-
Swift 中的命名空间是基于模块(module)的, 每个 module 代表了 Swift 中的一个命名空间, 而同一个命名空间中的名字仍然不能冲突. 简单的说一个项目,一个库就是一个命名空间, 而在一个项目(命名空间)中所用名字哪里都可以使用, 不需要 Import.
另一种策略是使用类型嵌套的方法来指定访问的范围.
详细请看>>王巍 (@ONEVCAT): 命名空间
-
C++中的命名空间是为了防止名字冲突, 给防止名字冲突提供了更加可控的机制.
-
C++代码中那些看起来巨长的类型名字
- 现代 C++语言实际上是由三部分组成的:
低级语言, 大部分继承自 C语言. 比如:可以创建 C 数组
std::string aCArray[4] = {...};
现代高级语言特性, 允许我们定义自己的类型以及组织大规模程序和系统.
标准库, 它利用高级特性来提供有用的数据结构和算法.
比如:vector
,string
,map
就是标准库提供的,所以如果没有任何说明的话, 就需要使用::
运算符来使用来自标准库中内容(vector
,string
,map
等).
而标准库的命名空间的名字为std
, 所以才出现像std::string
,std::vector
,std::map
这样的代码
- 现代 C++语言实际上是由三部分组成的:
-
使用 using 声明等方法避免巨长的类型名字的书写.
例如写入:using namespace std;
后就可直接使用 string,vector, map 等名字了, 当然还有其他方法, 以后再详细介绍- 比如上面的代码可以修改为:
- 比如上面的代码可以修改为:
include <iostream>
// 注意, 在 C++ 中, 下面这些东西统称为容器.
include <string> // 包含 string 来创建字符串
include <vector> // 包含 vector 来创建向量(类似数组), 另外也可以包含 array 来创建C++数组, 当然也可以声明也不包含直接创建 C 数组, 其实 string 是一种字符数组
include <map> // 包含 map 来创建有序的不重复关联数组. 另外也可以包含 unordered_map、 multimap、 unordered_map_multimap来分别创建无序的不重复的关联数组、有序的可重复的关联数组、 无序的可重复的关联数组
using namespace std; // 表示在下面的代码中可以直接使用来自命名空间 std 中的所有名字
int main() {
// 在创建的时候就不能使用 auto 进行类型推断了, 需要先指明类型, 再写变量名
string aCArray[4] = {"catfish", "water", "tulips", "blue paint"}; // 创建 C 数组
aCArray[1] = "bottle of water";
// 创建 vector 需要在<>中指明 vector 中包含元素的类型
vector<string> aVector = {"catfish", "water", "tulips", "blue paint"};
aVector[1] = "bottle of water";
// 创建 map 需要在<>中分别指明 map 键和值的类型
map<string, string> aMap = {
{"Malcolm", "Captain"},
{"Kaylee", "Mechanic"},
}; // std::map<std::string, std::string> 表示使用 std 标准库中的无序的关联数组, 其中键值的类型分别使用标准库 std 中的 string
aMap["Jayne"] = "Public Relations";
// 创建空向量/数组以及空字典
vector<string> aEmptyArray;
map<string, string> aEmptyMap;
// 现在可以使用 auto 了
auto aCArray2 = aCArray;
auto aMap2 = aMap;
return 0;
}
```