C++的一些问题

类相关

class和struct的异同?

相同点:

  1. 都可以包含成员变量(属性)和成员函数(方法)
  2. 都支持访问控制修饰符(publicprivateprotected
  3. 都可以继承其他类 / 结构体,也可以被继承
  4. 都可以包含构造函数、析构函数
  5. 都可以实现多态、模板等 C++ 特性
  6. 都可以使用friend声明外部函数或类

不同点:

特性structclass
默认访问权限成员默认是public成员默认是private
默认继承方式默认是public继承默认是private继承
传统用途主要用于存储数据(C 风格结构体的扩展)主要用于实现面向对象的类(封装数据和操作)
模板参数不能作为模板参数的关键字(C++11 前)可以作为模板参数的关键字

使用建议:

  • 当需要一个主要用于存储数据的简单结构时,使用struct
  • 当需要实现封装性强、包含复杂逻辑的面向对象类时,使用class
  • 保持代码风格一致性,避免混用造成混淆
 

实际上,structclass在 C++ 中本质上是相似的,只是默认行为不同,开发者可以根据需求灵活选择。

什么是C++仿函数

在 C++ 中,仿函数(Functor) 是一种重载了operator()的类或结构体实例。它的行为类似函数,但可以像对象一样存储状态,因此也被称为函数对象(Function Object)

仿函数的特点:

  1. 兼具函数和对象的特性:可以像函数一样被调用,同时可以拥有成员变量和成员函数来保存状态
  2. 可定制性:通过不同的成员变量值,同一个仿函数类可以表现出不同的行为
  3. 适配性好:广泛用于 STL 算法中(如sortfind_if等),作为自定义操作的参数

仿函数 vs 普通函数:

  • 仿函数可以携带状态(通过成员变量),普通函数不行
  • 仿函数可以被模板特化,普通函数不行
  • 仿函数的类型是明确的,可用于模板参数推导
  • 在性能上,仿函数调用通常可以被编译器内联优化,效率可能高于函数指针
 

C++11 及以后,lambda 表达式提供了更简洁的匿名函数对象实现,但仿函数在需要复用或需要复杂状态管理的场景下仍然非常有用。

一般性问题

函数和函数指针的类型是什么,有什么决定

在 C++ 中,函数和函数指针都有明确的类型,其类型由函数的参数列表返回值类型共同决定,与函数名或指针变量名无关。

1. 函数的类型

函数的类型由两部分决定:

  • 参数列表(参数的类型、数量、顺序)
  • 返回值类型

例如:

 
// 函数1:参数为int,返回值为int
int add(int a, int b) { return a + b; }

// 函数2:无参数,返回值为void
void print() { cout << "hello" << endl; }
 
  • 函数add的类型是:int(int, int)(可理解为 “接受两个 int 参数,返回 int 的函数”)
  • 函数print的类型是:void()(可理解为 “无参数,返回 void 的函数”)

2. 函数指针的类型

函数指针是指向函数的指针变量,其类型与它所指向的函数的类型完全一致,同样由参数列表返回值类型决定。

 

定义函数指针时,需要显式指定其指向的函数类型:

 
// 定义函数指针类型(与add函数类型匹配)
int (*func_ptr1)(int, int); 

// 定义函数指针类型(与print函数类型匹配)
void (*func_ptr2)(); 
 
  • func_ptr1的类型是:int(*)(int, int)(指向 “接受两个 int 参数,返回 int 的函数” 的指针)
  • func_ptr2的类型是:void(*)()(指向 “无参数,返回 void 的函数” 的指针)

3. 类型匹配规则

函数指针只能指向与其类型完全匹配的函数:

  • 参数列表必须完全一致(类型、数量、顺序)
  • 返回值类型必须完全一致
 
int add(int a, int b) { return a + b; }
int sub(int a, int b) { return a - b; }
double mul(double a, double b) { return a * b; }

int main() {
    int (*calc)(int, int); // 函数指针类型:int(*)(int, int)
    
    calc = add;  // 合法:类型匹配
    calc = sub;  // 合法:类型匹配
    calc = mul;  // 非法:参数和返回值类型不匹配(double vs int)
    return 0;
}

4. 简化函数指针类型的方法

复杂的函数指针类型可以通过typedefusing(C++11)简化:

 
// 方法1:typedef
typedef int (*CalcFunc)(int, int); 
CalcFunc func1 = add; // 等价于 int(*func1)(int, int) = add;

// 方法2:using(更直观)
using PrintFunc = void(*)(); 
PrintFunc func2 = print; // 等价于 void(*func2)() = print;

总结

  • 函数的类型由参数列表返回值类型共同决定。
  • 函数指针的类型必须与它所指向的函数类型完全一致。
  • 函数名本身不是类型,但可以隐式转换为对应函数指针类型的右值。

STL相关

在一个空的map中直接使用 map[key] = value; 会有问题吗​

在 C++ 中,在一个空的 std::map 中直接使用 map[key] = value; 语法是完全没有问题的。

这是因为 std::map 的 operator[] 操作符设计具有一个特殊的行为:当指定的键(key)在 map 中不存在时,它会自动插入一个新的键值对。具体来说:

  1. 首先,会在 map 中插入一个新元素,键为 key,值为该类型的默认构造值

  2. 然后,返回对这个新插入值的引用

  3. 最后,通过赋值操作符 = 将 value 赋给这个引用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值