C++ 基础
文章目录
前言
一、函数
1、三种函数相关的语言特性:
- 默认实参
- 内联函数
- constexpr函数
(1)默认实参作为形参的初始值出现在参数列表中
string screen( int height, int width = 65, char background =' '); //
(2)内联函数 inline
编译器会在每处调用内联函数的地方将内联函数的内容展开,避免因函数调用做出对现场进行压栈保存、并在调用结束后出栈恢复现场所用的开销。
inline string & shorterString(const string &s1, const string &s2){
return s1.size() <= s2.size() ? s1 : s2;
}
- 定义在类内部的成员函数是自动inline的
(3)constexptr函数是能用于常量表达式的函数。
①constexptr函数的返回值及所有形参的类型都得是字面值类型;
②函数体中有且仅有一条return语句。
③constexptr函数被隐式地指定为内联函数。
2、预处理帮助
-
assert预处理宏
-
NDEBUG预处理变量
(1)assert预处理宏:assert宏使用一个表达式作为它的条件:
assert(exptr);
如果exptr为假,assert输出信息并终止程序;如果exptr为真,assert什么也不做。
(2)NDEBUG预处理变量:定义NDEBUG可关闭调试状态,避免检查各种条件所需的运行时开销。
#define NDEBUG
可以使用NDEBUG编写条件调试代码
#ifndef NDEBUG
.... //如果NDEBUG未定义,则将会执行此段代码;否则将会忽略此段代码
#endif
assert的行为依赖于NDEBUG变量,如果定义了NDEBUG,则assert什么都不做;默认状态下没有定义NDEBUG。
3、函数指针:函数指针指向函数
函数的类型由返回类型和形参类型共同决定,与函数名无关。因此在声明函数指针的时候,直接用指针替换函数名:
bool lengthCompare(const string &, const string &); //函数
bool (*p)(const string &, const string &);//函数指针
//函数指针赋值
p = lengthCompare;//p直线名为lengthCompare的函数
p = &lengthCompare;//将lengthCompre函数的地址赋值给p指针
//通过指针调用函数
bool b1 = p("hello", "good");
bool b2 = (*p)("hello", "good");
bool b3 = lengthCompare("hello", "good");
函数指针作形参:
void useBigger(const string &s1, const string &s2,
bool p(const string &, const string &));//函数指针作形参
//等价声明:
void useBigger(const string &s1, const string &s2,
bool (*p)(const string &, const string &));
二、使用步骤
1.类
1.1 构造函数
- 默认构造函数
- 拷贝构造函数
(1)默认构造函数:在类没有显示声明任何构造函数时,编译器会自动生成默认构造函数(合成构造函数)。
通常需要自己定义默认构造函数:
①在声明其他类型的构造函数之后,编译器不会生成合成默认构造函数,需自己定义。
②当类的内置类型或者符合类型的成员都被赋予类内初始值时,该类才适合于使用合成默认构造函数;
③对于含有其他类类型的成员,且改类没有默认构造函数时,必须为当前类定义默认构造函数
【其他】构造函数不能用const来修饰,因为const修饰的是this指针,加上const之后就无法对对象的值进行赋值。
【其他】 构造函数不能用static修饰,因为静态函数没有this指针。
1.2 析构函数
【其他】定义一个类时,编译器将合成六个默认函数:
- 构造函数
- 拷贝构造函数
- 析构函数
- 赋值操作符重载
- 取地址操作符重载
- const修饰的取地址操作符重载
1.3 类的访问控制与封装
友元:类允许其他类或者非成员函数访问该类的非公有成员,方法是令其他类或者函数成为该类的友元。
声明说明:A用到类B的非公开成员,则在类B中声明A为友元函数/类:
class Sales_data{
//友元函数
friend Sales_data add_data(const Sales_data &, Sales_data &); //函数add_data()访问Sales_data的成员,此处友元声明仅指定访问权限
// 友元类
friend class Cost_data;//Cost_data类访问Sales_data的承运
public:
Sales_data() = default;
...
private:
double revenue = 0.0;
};
Sales_data add_data(const Sales_data &, Sales_data &);//类外声明/定义(友元)函数
为了使友元对用户可见,通常在类外需要再专门对函数进行一次声明。
// 友元成员函数
class A;//B中依赖于A,故在B之前声明A
class B{
public:
void set_show(int x, A&a);
...
};
class A{
friend void B::set_show(int x, A&a);//友元成员函数声明
public:
...
};
2.动态内存
2.1直接管理内存 new、delete
2.2智能指针
指向动态内存的普通指针要通过delete销毁该对象并释放与之关联的内存。
显示释放内存够很容易出现问题:忘记释放内存——产生内存泄露;在尚有指针引用的情况下释放指针——产生引用非法的内存指针。
智能指针的作用是负责自动释放所指向的对象。可更容易、更安全地使用动态内存。
- shared_ptr 允许多个指针指向同一个对象
- unique_ptr 独占所指向的对象
- weak_ptr 是一种弱引用,指向shared_ptr所管理的对象
智能指针也是模板,创建智能指针时需要提供指针可以指向的类型:
shared_ptr<string> p1;//指向string类型的智能指针
shared_ptr
每个shared_ptr都有一个关联的计数器用于进行引用计数(记录有多少个其他的shared_ptr指向相同的对象)。
拷贝shared_ptr会使计数器递增;
赋值会使 右值 指向对象的引用计数递增,递减 左值 原来指向对象的引用计数
// 智能指针定义及初始化方式一:
auto r = make_shared<int>(42);//构建一个shared_ptr r,r指向的int类型对象只有一个引用(r本身)
r =q;//给r赋值,令r指向另一地址
// q的引用计数递增
// r原来指向对象的引用计数递减
// r指向新的对象
shared_ptr计数器变为0时,会通过析构函数释放所管理的对象的内存。
// 智能指针的定义及初始化方式二:
shared_ptr<int> (new int(42)); // 因为智能指针的构造函数是显示的explicit,必须使用直接初始化形式
shared_ptr<int> = new int(42); // 错误
unique_ptr
某个时刻只能有一个unique_ptr指向一个给定的对象。unique_dir被销毁时,它指向的对象也被销毁。
定义:
unique_ptr<int> p1;//定义指向一个int类型对象的unique_ptr
unique_ptr<int> p2(new int(42));//定义并显示初始化
unique_ptr 不支持 普通拷贝 或 赋值 操作
可通过release和reset将指针的所有权从一个非const的unique_ptr转移给另一个unique_ptr:
unique_ptr<string> p2(p1.release());//p2被初始化为p1保存的指针,p1置空
p2.reset(p3.release());//将所有权从p3转移给p2
2.3
shared_ptr和new结合使用
在这里插入代码片
代码如下(示例):
data = pd.read_csv(
'https://labfile.oss.aliyuncs.com/courses/1283/adult.data.csv')
print(data.head())
该处使用的url网络请求的数据。
总结
提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。