前言
即将开展的任务主打C++,不敢说以前没有接触,但实在都是零散的了解(与能参与项目开发还有非常大差距),所以打算从头开始C++的学习与实践,在此记录过程。
知识重点
昨天通过一道题目的练习,基本理解并掌握以下几个知识点:
const引用
练习时候遇到的问题:
分析知识点:
1,常量初始化对于非const引用不合法,导致编译错误;
原因:“引用”在内部存放的是一个对象的地址,它是该对象的别名。对于不可寻址的值(如文字常量)以及不同类型的对象,编译器为了实现引用,必须生成
一个临时对象,引用实际上指向该临时对象,但用户不能访问它。C++规定,不允许非const引用指向生成的临时对象或值,否则访问该临时对象或值
可能引起值变化;而const引用本身只允许可读,所以不存在对temp值进行访问修改。
<span style="font-family:SimSun;font-size:18px;">举例:
double dval = 1024;
const int &ri = dval;
编译器将其转换成:
int temp = dval;
const int &ri = temp; // ri实际指向temp,并且用户不能访问temp</span>
2,实际的C++程序很少使用指向独立的引用类型。引用类型多被用作函数的形参;
<span style="font-family:SimSun;font-size:18px;">举例:
string Add(const string &str1, const string &str2);
Add("111","222")
等价于
const string &str1 = "111";
const string &str2 = "222"; // 由此,如果没有const修饰词,则知识点1引起编译报错;</span>
3,引用类型作为函数参数场景;(这里参数传递机制属于传址,跟指针类似)- 必须将一个参数改变成指针来允许修改实参值;
- 向主调函数返回额外结果;
- 向函数传递大型类对象;
4,引用与指针的区别;
- 引用必须明确初始化对象,指针可以指向一系列对象或者不需要指向;
- 如果用一个引用给另一个引用赋值,那么改变的是被引用的对象而非该引用本身;
<span style="font-family:SimSun;font-size:18px;">举例: int ival = 1024, ival2 = 2048;
1)int *pi = &ival, *pi2 = &ival2;
pi = pi2; // pi、pi2共同指向ival2, ival值不变
2)int &ri = ival, &ri2 = ival2;
ri = ri2; // ri、ri2还分别指向ival,ival2, ival值改变 </span>
5,考虑到引用与指针做为形参的相似性,如何确定将形参声明为引用还是指针?- 如果一个参数可能在函数中指向不同的对象或者这个参数可能不指向任何对象则必须使用指针参数;
- 在需要有效实现重载操作符的同时还能保证用法的直观性时用引用参数;(支持类class 类型,尤其是支持有效直观地实现重载操作符机制C++特别引入了引用机制)
string类用法
练习过程中我主要熟悉了string类的常用方法,重点使用了insert()重载函数,下面列出insert方法原型:
<span style="font-family:SimSun;font-size:18px;">(摘自网络)
string &insert(int p0, const char *s);
string &insert(int p0, const char *s, int n);
string &insert(int p0, const string &s);
string &insert(int p0, const string &s, int pos, int n); //在p0位置插入字符串s中pos开始的前n个字符
string &insert(int p0, int n, char c); //在p0处插入n个字符c
iterator insert(iterator it, char c); //在it处插入字符c,返回插入后迭代器的位置
void insert(iterator it, const_iterator first, const_iterator last); //在it处插入[first,last)之间的字符
void insert(iterator it, int n, char c); //在it处插入n个字符c</span>
实例
【练习】任意位数的正整数字符串加法。
练习要求
1,实现Add函数,该函数完成两个任意位数的正整数字符串相加;【要字符串按位计算来实现】
<span style="font-family:SimSun;font-size:18px;">例如:
Add("1","2") == "3"
Add("99","2") == "101"
Add("123456789123456789123456789", "222") == "123456789123456789123457011"</span>
2,采用TDD方式开发,产品代码跟测试用例代码分离;实现思路
举个例子,如图示:
代码实现
<span style="font-family:SimSun;font-size:18px;">/* test.cpp */
#include <assert.h>
#include <string>
using namespace std;
extern string Add(const string &str1, const string &str2);
void main()
{
assert(Add("1","2") == "3");
assert(Add("1","9") == "10");
assert(Add("2","9") == "11");
assert(Add("1","99") == "100");
assert(Add("1","999") == "1000");
assert(Add("1","9999") == "10000");
assert(Add("2","99") == "101");
assert(Add("12345","99") == "12444");
assert(Add("123456789123456789123456789", "222") == "123456789123456789123457011");
getchar();
}
</span>
<span style="font-family:SimSun;font-size:18px;">/* add.cpp */
#include <iostream>
#include <string>
using namespace std;
typedef unsigned int uint;
void AddInit(const string &str1, const string &str2, string &temp_str, string &result)
{
if (str1.size() >= str2.size())
{
temp_str = str2;
temp_str.insert(temp_str.begin(), str1.size() - str2.size(), '0');
result = str1;
}
else
{
temp_str = str1;
temp_str.insert(temp_str.begin(), str2.size() - str1.size(), '0');
result = str2;
}
}
string Add(const string &str1, const string &str2)
{
uint carry_bit = 0;
uint temp_value = 0;
string result, temp_str;
AddInit(str1, str2, temp_str, result);
uint index = result.size() - 1;
for (uint i = 0; i < result.size(); i++)
{
temp_value = (result[index - i] - '0') + (temp_str[index - i] - '0') + carry_bit;
carry_bit = temp_value / 10;
temp_value = temp_value % 10;
result[index - i] = temp_value + '0';
}
if (carry_bit > 0)
{
result.insert(result.begin(), carry_bit + '0');
}
cout << ">:" << result << "\n";
return result;
}</span>
优化修改
<span style="font-family:SimSun;font-size:18px;">/* test.cpp */
#include <assert.h>
#include <string>
using namespace std;
extern string Add(const string &str1, const string &str2);
void No_Carrybit_Test()
{
assert("3" == Add("1","2"));
}
void Single_Carrybit_Test()
{
assert("10" == Add("1","9"));
assert("11" == Add("2","9"));
}
void Multi_Carrybit_Test()
{
assert("100" == Add("1","99"));
assert("1000" == Add("1","999"));
}
void Complex_Operation_Test()
{
assert("101" == Add("2","99"));
assert("198" == Add("99","99"));
assert("12444" == Add("12345","99"));
assert("123456789123456789123457011" == Add("123456789123456789123456789", "222"));
}
void main()
{
No_Carrybit_Test();
Single_Carrybit_Test();
Multi_Carrybit_Test();
Complex_Operation_Test();
getchar();
}
</span>
<span style="font-family:SimSun;font-size:18px;">/* add.cpp */
#include <iostream>
#include <string>
using namespace std;
#define NumToStr(x) (x + '0')
typedef unsigned int uint;
uint GetNum(const string &str, uint index)
{
uint temp_value = 0;
if (index < str.length())
{
temp_value = str[str.length() - 1 - index] - '0';
}
return temp_value;
}
string Add(const string &left, const string &right)
{
uint carry_bit = 0;
string result = left.size() >= right.size() ? left : right;
for (uint i = 0; i < left.size() || i < right.size(); i++)
{
uint temp_value = GetNum(left, i) + GetNum(right, i) + carry_bit;
carry_bit = temp_value / 10;
temp_value = temp_value % 10;
result[result.length() - 1 - i] = NumToStr(temp_value);
}
if (carry_bit > 0)
{
result.insert(result.begin(), NumToStr(carry_bit));
}
cout << ">:" << result << "\n";
return result;
}</span>
总结
主要参考
《C++ Primer》