zoukankan      html  css  js  c++  java
  • 1.1C++入门 未完待续。。。

    第一个C++程序:

     #include<iostream>
    int main()
    {
    	std::cout << "Hello World !" << std::endl;
    	return 0;
    }
    

    C++中C的头文件仍然能够使用。
    编译程序

     g++ -o main.o -c main.cpp
    

    链接

     g++ -o main.exe main.o
    

    命名空间:是给代码指定的名称,有助于降低命名冲突的风险,通过使用std::cout,可命令编译器调用名称空间std中独一无二的cout。位于namespace下面的类型或者函数都不是全局的,使用的时候必须使用namespace作为前缀,这跟寻找文件必须采用绝对路径道理相同。而且头文件中禁止使用using语句
    使用cin和cout执行基本的输入输出操作:
    要将简单的文本数据写入到控制台,可使用std::cout,要从终端读取文本,可以使用std::cin。

    C++新增了bool类型来表示真假,C++支持的数据类型有:bool、char、int、float、double、long等。

    使用typedef可以简化类型定义

    typedef unsigned int UNIT;
    

    赋值与初始化

    int i = 9;
    int i(9);
    j = 10;
    

    这三条语句中,a和b是初始化语句,c是赋值语句

    引用类型
    引用是变量的别名。在声明引用的时候,需要将其初始化为一个变量,因此引用只是另一种访问相应变量存储数据的方式。要声明引用可以使用引用运算符(&),如下:

    int num =  99;
    int &num_ref = num;	
    

    注意:无论将引用初始化为变量还是其他引用,它都指向相应变量所在的内存单元。因此引用是真正的别名,即相应变量的另一个名字。
    交换两个变量,使用引用的版本:

     template<typename T>
     void swap(T &a, T &b)
     {
    	 T temp(a);
    	 a = b;
    	 b = temp;
     }
    

    在C++中禁止使用memset、memcpy、memcmp等直接操控内存的操作,知道你理解一个概念POD(原生数据类型)。

    在C++中关于string的加法有四种组合:a)string + char* b)string + string c)char* + string d)char + char*(不合法)*
    例如:

    string s2 = s1 + "orange" + "apple";
    string s3 = "orange" + s2 + "banana";
    string s4 = s3 + "a" + "b" + "c";
    cout << s2 <<endl<<s3<<endl<<s4<<endl;
    

    //这种是错误的

    string s5 = "a" + "b" + s2;
    

    如果前两个字符串相加合法(生成了一个string对象),那么整条表达式就合法。

    关于vector:(标准库类型)
    传统数组的缺点
    大小必须在编译时候确定,容易溢出。追加元素的时候需要一个i记录最后一个位置的下标,而且它是不可复制和赋值的。在C中,我们还可以通过在heap上开辟内存的方式来获取动态的数组,这样的好处是可以在运行期决定数组的大小,但是管理麻烦,如果忘了手工free内存,就会造成内存泄露。
    vector就可以克服上面的诸多缺点,它不是一个完整的类型,必须加上内置的类型,例如vector、vector;vector不要越界访问,否则结果是未定义的。而且vector内的元素都是副本,与之前的变量无关联。
    vector可以直接定义一个空数组也可以指定数组的大小,它也可以无限扩充不存在溢出问题。支持的操作有:1)下标访问 2)size() 3)push_back从数组的后面追加元素
    vector的使用方法:

    #include <iostream>
    #include <vector>
    using namespace std;
    int main()
    {
    	vector<int> col;//声明一个空数组
    	for(int i = 1; i <= 6; ++i)
    	{
    		col.push_back(i);//往数组中添加元素
    	}
    	//遍历打印
    	for(int i = 0; i < col.size(); ++i)
    	{
    		cout << col[i] << " ";
    	}
    	cout << endl;
    }
    

    这里我们采用的是声明一个空数组,后面给它追加元素的做法,事实上这是一种常见的做法。还有一种用法是,一开始制定好数组的大小,然后逐个进行赋值。

    #include <iostream>
    #include <vector>
    using namespace std;
    int main()
    {
    	vector<int> col(20);//数组大小为20
    	for(int i = 0; i != col.size(); ++i)
    	{
    		col[i] = i;//根据下标进行赋值
    	}
    	//遍历打印
    	for(int i = 0; i < col.size(); ++i)
    	{
    		cout << col[i] << " ";
    	}
    	cout << endl;
    }
    这里有一些注意点,就是下标不可越界访问,更加不可越界赋值,标准中规定越界为非定义行为,引发的后果是未知的。
    

    关于迭代器
    迭代器是一个“可遍历全部或者部分元素”的对象,但是它的表现行为像是一个指针。
    四个特殊的迭代器:
    a)begin:第一个元素
    b)end:最后一个元素的下一个位置
    c)rbegin:最后一个元素
    d)rend:第一个元素的前一个位置

    string s;
    for(string::iterator it = s.begin(); it != end(); ++it)
    {
    	cout << *it << endl;
    }
    

    正向打印数组:

    #include <iostream>
    #include <vector>
    using namespace std;
    int main()
    {
    	vector<int> col(20);
    	for(int i = 0; i != col.size(); ++i)
    	{
    		col[i] = i;
    	}
    	for(vector<int>::iterator iter = col.begin(); iter != col.end(); ++iter)
    	{
    		cout << *iter << " ";
    	}
    	cout << endl;
    }
    

    这里有几处注意点:
    对vector调用begin,得到的是一个迭代器,指向vector的第一个元素。
    对vector调用end,返回一个迭代器,注意,它指向的是容器最后一个元素的下一个位置,也就是说,它指向的是一个不存在的位置。
    于是begin和end就构成了一个半开区间,从第一个元素开始,到最后一个元素的下一个位置结束。半开区间有两个优点:
    1.为“遍历元素时,循环的结束时机”提供了一个简单的判断依据。只要尚未到达end,循环就可以继续进行。
    2.不必对空区间采取特殊处理手法。空区间的begin等于end
    使用迭代器逆向打印数组:

    #include <iostream>
    #include <vector>
    using namespace std;
    int main()
    {
    	vector<int> col(20);
    	for(int i = 0; i != col.size(); ++i)
    	{
    		col[i] = i;
    	}
    	for(vector<int>::reverse_iterator iter = col.begin(); iter != col.end(); ++iter)
    	{
    		cout << *iter << " ";
    	}
    	cout << endl;
    }
    
    

    这里跟刚才使用迭代器有几处区别:
    1.使用的不再是iterator,而是reverse_iterator
    2.调用的也不再是begin和end,而是rbegin和rend,注意rbegin指向最后一个元素,rend指向第一个元素的前一个位置。

    malloc&&free&&new&&delete
    malloc的工作原理:a)申请heap内存 b)将base地址返回
    malloc返回值是void*。malloc在申请内存成功后,会在该内存的前几个字节处,记录下内存块的详细信息。malloc申请的内存空间是没有初始化的。绝对不要使用malloc申请string

    free只做一件事情:释放内存。free时,系统自动查找该信息块,获取到内存的大小,然后进行释放。

    new:申请heap内存(原始内存)、对数据进行构造(new执行了对数据的初始化)、返回地址为申请的指针类型。

    delete:销毁数据、释放内存

    new、delete一定要配对使用:a)new申请数组一定要用delete[] b)new申请的内存不可以使用free。用malloc申请的内存,绝不可以使用delete。

    new和malloc的区别
    a)new是运算符,malloc是函数
    b)new要执行对象的构造工作,malloc仅仅申请原始字节
    c)malloc的数据是未初始化的。

    string类型:(C标准库类型)
    C风格字符串的缺陷:
    1.恼人的结束符‘’
    2.很多时候需要手工保证安全性,例如下面的代码就可能导致程序崩溃。

    #include <iostream>
    #include <string.h>
    using namespace std;
    int main()
    {
    	char buf[3];
    	strcpy(buf, "hello");
    	cout << buf << endl;
    }
    

    这里错误的原因在于buf的内存空间不够,于是内存越界,但是strcpy不会也无法检查内存是否越界。C++的解决方案是引入了string。你可以把string当做一个一般的类型去使用,而不会发生任何问题。

    C风格字符串可进行的操作有
    strlen 求长度
    strcpy 复制字符串
    strcmp 比较字符串大小
    strcat连接字符串
    这些在string中均可以进行,而且更加简单,没有任何的安全隐患。
    string用法如下:

    #include <iostream>
    #include <string>
    #include <vector>
    using namespace std;
    
    int main() {
    
    	string s1 = "hello";
    	string s2("test");
    	string s3;	//空字符串
    
    	cout << s1 << endl; //打印字符串
    	cout << s1.size() << endl; //求长度
    	s3 = s1;  //字符串间的复制
    	s3 += s2;	//字符串的拼接
    	cout << s3 << endl;
    
    	//比较大小
    	cout << (s1 < s2) << endl;
    	cout << (s1 == s3) << endl;
    }
    

    string同样支持下标操作,所以可以采用下标遍历:

    #include <iostream>
    #include <string>
    #include <vector>
    using namespace std;
    
    int main() {
    
    	string s = "who are you?";
    
    	for (size_t ix = 0; ix != s.size(); ++ix) {
    		cout << s[ix] << " ";
    	}
    	cout << endl;
    }
    

    同样支持迭代器iterator和逆置迭代器reverse_iterator

    #include <iostream>
    #include <string>
    #include <vector>
    using namespace std;
    
    int main() {
    
    	string s = "who are you?";
    
    	for (string::iterator iter = s.begin(); iter != s.end(); ++iter) {
    		cout << *iter << " ";
    	}
    	cout << endl;
    
    	for (string::reverse_iterator iter = s.rbegin(); iter != s.rend(); ++iter) {
    		cout << *iter << " ";
    	}
    	cout << endl;
    }
    

    在string中查找字符:

    #include <iostream>
    #include <string>
    using namespace std;
    
    int main(int argc, char **argv) {
    	string s = "American";
    
    	string::size_type pos = s.find('i');
    	if (pos != string::npos) { //查找成功
    		cout << pos << endl;
    	} else {					//没有找到
    		cout << "not found!" << endl;
    	}
    }
    

    使用的find函数,这里要对查找结果进行判断。
    string可以转化为C风格字符串:

    string s = "Shenzhen";
    cout << s.c_str() << endl;
    

    注意:string得出的char*是const属性,也就是说只可以读取它的值,不可以对其进行改动。
    另外这个值可能失效,所以如果需要操作字符串,最好是复制一份。

    如何整行读入字符串:使用getline
    代码如下:

    #include <iostream>
    #include <string>
    using namespace std;
    
    int main() {
    	string s;
    	getline(cin, s);
    	cout << s << endl;
    }
    
  • 相关阅读:
    用POP动画模拟真实秒钟摆动效果
    解析苹果的官方例子LazyTableImages实现图片懒加载原理
    支持xcode6的缓动函数Easing以及使用示例
    [转] iOS 动画库 Pop 和 Canvas 各自的优势和劣势是什么?
    NSJSONSerialization能够处理的JSONData
    [翻译] USING GIT IN XCODE [6] 在XCODE中使用GIT[6]
    [翻译] USING GIT IN XCODE [5] 在XCODE中使用GIT[5]
    [翻译] USING GIT IN XCODE [4] 在XCODE中使用GIT[4]
    [翻译] USING GIT IN XCODE [3] 在XCODE中使用GIT[3]
    【转】断点继传
  • 原文地址:https://www.cnblogs.com/stardujie89/p/3995927.html
Copyright © 2011-2022 走看看