您的位置:首页 > 其它

Note10

2017-01-14 18:51 225 查看
指针和引用的区别:

(1) 引用总是指向某个确定对象,引用就是对象的别名,定义引用时没有进行初始化会出现编译错误;

(2) 赋值行为上存在差异:给引用赋值修改的是该引用所关联的对象的值,而不是使该引用与另一个对象关联。引用一经初始化,就始终指向同一个特定对象。给指针赋值修改的是指针对象本身,也就是使指针指向另一个对象,指针在不同时刻可指向不同的对象,只要保证类型匹配。

strtok

#include <iostream>
#include <string>
#include <list>
using namespace std;
int main()
{
string input;
getline(cin, input);
char token[] = {',','。','!','?','-'};
int length = sizeof(token) / sizeof(token[0]) - 1;
for (size_t i = 0; i < length; i++)
{
size_t location = input.find(token[i]);
while (location < input.length())
{
input = input.replace(location, 1, " ");
location = input.find(token[i]);
}
}
char str[200];
strcpy(str, input.c_str());
char *pch;
pch = strtok(str, " ");
list<string> result;
while (pch != NULL)
{
result.push_back(pch);
pch = strtok(NULL, " ");
}

for (string temp : result)
{
cout << temp << endl;
}
system("pause");
return 0;
}


函数参数传递时尽量使用const引用形参

第一:尽量以pass-by-reference-to-const 替换pass-by-value,前者通常高效,不会有构造函数和析构函数的发生(注意const是重要的,原因第一在我的const用法全面总结说过 (灵活性);第二传值是传的是副本,即使在函数中修改了副本,但是实参照样没被修改。所以改成引用必须加上const以保证函数不会对实参进行修改,如果 不这样做的话调用者会忧虑函数会不会改变他们传入的那个实参)。并可以避免切割问题。

第二:第一条规则并不适合内置类型,以及STL的迭代器和函数对象,对它们而言,传值往往比较适当。因为他们都比较小,且习惯上他们都被设计成传值。

引用在C++编译器底层是往往用指针实现的,所以传引用往往意味着真正传递的是指针。

因此有人认为所有小型对象都应该传值,甚至他们是用户自定义的class。这也是错误的。因为:

(1)对象小不意味着copy构造函数不昂贵。许多对象——包括大多数STL容器——内含的东西只比一个指针多一些,但复制这种对象却需要承担“复制那些指针所指的每一样东西”。那将非常昂贵。

(2)即使小型对象拥有并不昂贵的copy构造函数,还是可能有效率上的争议。某些编译器对待“内置类型”“和用户自定义类型”的态度截然不同,纵使两者拥有相同的底层描述。如:某些编译器拒绝把只有一个double组成的对象放进缓存器内,却很乐意在一个正规基础上对光秃秃的double那么做。当这种事发生,更应该以引用传递此等对象,因为编译器肯定会将指针(引用实现体)放进缓存内。

(3)作为一个用户自定义的类型,其大小容易有所变化。一个type目前虽然小,将来也许会变大,因为其内部实现可能改变。甚至当你改用另一个C++编译器都有可能改变对象的大小。

什么时候应使用指针形参?什么时候应使用引用形参?解释两者的优点和缺点

当函数需要处理数组且函数体不依赖于数组的长度时应使用指针形参,其他情况下应使用引用形参。

指针形参的优点是可以明确地表示函数所操纵的是指向数组元素的指针,而不是数组本身,而且可以使用任意长度的实参数组来调用函数;其缺点是函数体不能依赖于数组的长度,否则容易造成数组内存的越界访问,从而产生错误的结果或者导致程序崩溃。

引用形参的优点是在函数体中依赖数组的长度时安全的;其缺点是限制了可以传递的实参数组,只能使用长度匹配的实参数组来调用函数。

流类型不能作为函数的形参或返回类型,必须使用流类型的指针或引用。

不可以使用容器来存储iostream对象

因为容器元素类型必须支持赋值操作及复制,而iostream类型不支持赋值和复制;

复制容器对象的构造函数和使用两个迭代器的构造函数之间的差别

复制容器对象的构造函数只能将一个容器初始化为另一个容器的副本(即复制另一容器的全部元素),这种构造函数要求两个容器是同类型的;使用两个迭代器的构造函数可以将一个容器初始化为另一容器的子序列(即复制另一容器的一个子序列),而且采用这种构造函数不要求两个容器是同类型的。

class和struct定义类的区别

默认的访问标记不同:class定义的类中,默认为private成员;struct定义的类中,默认为public成员。

内联函数:减少函数调用的开销–特别是对于小函数

在函数中限定符inline放在函数的返回类型的前面,会“建议”编译器在适当的地方生成函数代码的副本一避免函数调用。这种折中办法是把函数代码的多份副本插入到程序中(通常会使程序变大),而不是仅有一份函数代码,每次调用函数时都把控制权传递给它。编译器可以忽略inline限定符,并且对于除了小函数之外的函数,通常都会这样做。

static

static数据成员必须在类定义体外部定义,且之定义一次。一般可将它放在类的实现文件中。

重载操作符与内置操作符的异同

不同:重载操作符必须具有至少一个类类型或枚举类型的操作数;重载操作符不保证操作数的求值顺序,例如,&&和||的重载版本失去了“短路求值”特性,两个操作数都要进行求值,而且不规定操作数的求职顺序。

同:操作符的优先级、结合性及操作数数目均相同。

重载操作符

+、<<和==操作符通常应定义为非成员函数,但<<操作符通常需要访问类的数据成员,所以一般应制定为类的友元。通常==和!=操作符应相互联系定义起来。

+=和++会改变对象的状态,通常应定义为类成员;

–>和()必须定义为类成员,否则会出现编译错误。重载的箭头操作符不接受显式形参,且必须返回指向类类型的指针,或返回定了箭头操作符的类类型对象;需要定义const版本和非const版本。

&&一般对类类型操作符没有意义,通常不进行重载;如果一定要重载,可重载为非成员函数。

类定义下标操作符时,一般需定义两个版本,即返回引用的非const成员及返回const引用的const成员,以便可以对const和非const对象使用下标;可以对下标是否越界进行检查,以避免对内存的非法访问。

Class NoName
{
public:
NoName(Screen *p) :ptr(new ScreenPtr(p))
{
}
ScreenPtr operator->()
{
return *ptr;
}
const ScreenPtr operator->()
{
return *ptr;
}
private:
ScreenPtr *ptr;
}


使用容器的size_type和size成员控制打印元素的循环

#include <iostream>
#include <vector>
#include <string>
using namespace std;
template <typename Param>
void print(const Param& c)
{
typename Param::size_type index = 0;
while (index != c.size())
{
cout << c[index] << ' ';
++index;
}
}
int main()
{
int ia[] = {1,2,1,4,1,6,1};
string sa[] = {"this","is","Mary","test","example"};
vector<int> ivec(ia,ia+7);
vector<string> svec(sa, sa + 5);
print(ivec);
cout << endl;
print(svec);
system("pause");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: