欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

c++日常采坑集锦

程序员文章站 2022-04-15 18:09:32
...

学习C++踩的坑,持续更新中。。。

1、参考链接:初始化二维数组

visual格式化快捷键:Ctrl+K+F

2、将字符转换为字符串的方法:

  • string temp = “a”;
    temp[0] = s[i];//将字符转为字符串 放入数组中
  • 还可以使用C++内置的方法to_string;

3、C++语法中的一些注意细节:

(1)C++中的代码重用

  • C++对象构造函数中初始化列表的初始化顺序是变量被声明的顺序。
  • explicit防止单参数构造函数的隐式转换,const限制方法修改数据。
  • 在私有继承中,在不进行显式类型转换的情况下,不能将指向派生类的引用或指针赋给基类引用或指针。
  • 公有继承是is-a关系,私有继承和保护继承是has-a关系,私有继承常用于某个类需要调用到另外一个与之不同的类。
  • 私有继承在调用继承类的方法时,一般是通过类名和作用域解析运算符来调用方法。
  • 通常,应该使用包含来建立has-a关系,包含就是在一个类中包含其他类,如果新类需要访问原有类的保护成员,或者需要重新定义虚函数,则应该使用私有继承。
  • using声明只使用成员名,没有圆括号、函数特征标和返回类型。using只适用与继承,不适用与包含。

(2)类和动态分配内存

  • 类的所有对象共享同一个静态成员,不能在类声明中初始化静态成员变量,这是因为声明描述了如何分配内存,但并不分配内存

  • 删除对象可以释放对象本身占用的内存,但是并不能自动释放属于对象成员的指针指向的内存。因此,必须使用析构函数来删除new的内存。

  • 在构造函数中使用new来分配内存时,必须在相应的析构函数中使用delete来释放内存。如果使用new[]来分配内存,则应使用delete[]来释放内存。

  • 如果类中包含使用new初始化的指针成员,应当定义一个复制构造函数,以复制指向的数据,拷贝出副本,而不是指针,这就是深度复制。浅复制只是复制指针的信息

  • 深度拷贝也是为了防止在调用构造函数时,对象同时指向同一块内存,在调用析构函数时,删除同一块内存的内容,引发异常。

  • C++自定义的赋值运算符也可能导致在赋值同一个指针内容时,指向同一块内存,因此也需要自定义赋值运算符。

  • cin.get(temp,length)函数是从键盘上获取一个字符赋值给temp字符串,并且长度不能超过length,!cin检测输入的是否是空行,也可以使用C语言的方法temp[0]=’\0’。

  • 返回值返回指向const对象的引用的目的是为了提高效率。因为如果直接返回对象会调用赋值构造函数,而返回引用不会。

  • 如果使用返回类型ostream,将要求调用ostream类的复制构造函数,而ostream没有公有的复制构造函数。

  • 如果被返回的对象是被调用函数中的局部变量,则不应该按照引用方式返回它,因为在被调用函数执行完成时,局部对象将调用其析构函数。通常,算数运算符不用返回引用对象。

  • 析构函数被调用的场景:

    如果是动态变量,程序将在程序块结束时自动调用析构函数。

    如果对象是静态变量,则在程序结束时将调用对象的析构函数。

    如果对象是new创建的,则当显式使用delete删除对象时,其析构函数才会被调用。

  • 定位new运算符:

    Ex:
    char *buffer=new char[Length];
    Object *test=new(buffer) Object;

    Object *test1=new(buffer+sizeof(Object)) Object;

    这个例子表示的就是test对象是在buffer对象所开辟空间的基础上创建的,如果要析构此对象的话,需要显示析构,如:test->~Object(),注意:对于使用定位new运算符创建的对象,应以与创建顺序相反的顺序进行删除。原因在于,晚创建的对象可能依赖于早创建的对象。

  • 对于const数据成员,必须在执行到构造函数体之前,即创建对象时进行初始化,可以使用成员初始化列表来实现此操作。对于被声明为引用的类成员,也必须使用初始化列表来初始化。 对于本身就是类对象的成员来说,使用成员初始化列表的效率更高,而对于简单的数据成员,使用初始化列表和在函数体中使用赋值没有什么区别。

4、C++STL注意点

(1)sort算法
  • 当数据量大时,底层采用的是快速排序,分段递归排序。一旦分段后的数据量小于某个门槛(16),为避免快速排序的递归调用带来过大的额外负荷,就改用插入排序。(插入排序针对几乎是有序的序列效果很好)STL中定义了一个SORT_MAX变量来进行判断,如果大于SORT_MAX就使用快排,否则使用插排。如果因为递归太深还会改用堆排序。sort算法只适用于随机存取迭代器的容器,也就是vector容器和deque容器,list和slist容器使用本身的sort算法。枢轴的选择与快速排序的算法极为关键,可能使算法效率降低为平方级,因此当算法效率接*方级别时,会转为堆排序。

疑问:为什么必须是随机存取迭代器呢?
原因:因为在进行快速排序时,在枢轴时,一般采用取开头,中间,或结尾,为了快速获取中间位置,因此随机存取迭代器是最好的选择。

(2)bind1st与bind2nd的区别:
  • 这两个函数的作用是将二元函数转为一元函数,bind1st是将传入的参数放在第一个位置,bind2nd是将传入的参数放在第二个位置。如:
std::copy_if(std::begin(arr),std::end(arr),std::back_inserter(vec),std::bind1st(std::less<int>(),6));
//这里相当于6<value
std::copy_if(std::begin(arr),std::end(arr),std::back_inserter(vec),std::bind2nd(std::less<int>(),6));
//这里相当于value<6
相关标签: c++ 算法 stl