c++ - delete(void *, size_t) or delete(void *)

本文深入探讨了C++中overloaded delete和new操作符的使用,解释了它们的不同签名及其适用场景。重点讨论了在不同情况下选择使用void*或void*与size_t参数的原因,特别关注内存分配与释放的最佳实践。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

In my previous dicuss, we have seen the example of overloaded delete and new operator. and as a matter of fact, we have seen the following signature of the delete operator. 

 

 

void operator delete(void *);
void operator delete(void *, size_t size);

 

 

As you will soon find out that they both match the same new operator

 

void operator new (size_t);

 

but which one should we  choose to use?

 

and even, you can define both the operator delete(void *) and the operator delete (void *, size_t) in the same class, and according to my test , in the placement operator overloading example, the "operator delete(void *)" has precedance over the "operator delete (void *, size_t)"....

 

so here is my rule of thme, we uses operator delete (void *, size_t size) when 

 

  • the size_t is not barely the size of the object (this could happen if the new operator has say, preallocate some space which is larger than what is required by the object itself.)
  • the size_t is necessary to determine flows or it is necessary in the clean up that the delete operator is supposed to do.
  • Booking and logging requirement.
  • This can be thought as an extension to the point 2, where you can normally see allocated memory is larger than the object itself, is when you allocate a array (new [] operator actually does this)....

 

And when to use the operator delete (void *)?

 

  • when the size of the pointer in the first parameter is exact the size of the object
  • The size_t size is irrelevant in the deallocation flow. 

 

 

 

 

 

<think>我们在C++中,普通成员函数不能直接作为pthread_create的线程函数,因为非静态成员函数有一个隐式的this指针参数,导致其函数签名与pthread_create要求的`void* (*)(void*)`不匹配。 解决方案: 1. 将该成员函数声明为静态成员函数(static)。这样就去掉了隐式的this指针,使其函数签名匹配。 2. 但是静态成员函数不能直接访问非静态成员(包括成员变量和成员函数),因此我们需要将对象的this指针作为参数传递给线程函数。 3. 在线程函数内部,通过传递进来的this指针来访问对象的非静态成员。 具体步骤: 步骤1:定义一个静态成员函数作为线程入口函数,其参数和返回值必须为`void*`和`void*`。 步骤2:在创建线程时,将当前对象的指针(this)作为参数传递给线程函数(通过pthread_create的第四个参数)。 步骤3:在线程函数内部,将传入的void*参数转换为类的指针,然后通过该指针调用非静态成员函数。 注意:如果需要传递多个参数,可以定义一个结构体,将对象指针和其他参数一起传递。 示例代码: ```cpp #include <pthread.h> #include <iostream> class MyClass { public: void startThread() { // 创建线程,将this指针作为参数传递 int ret = pthread_create(&tid_, NULL, &MyClass::threadEntry, this); if (ret != 0) { // 错误处理 } } // 非静态成员函数,用于线程实际执行的任务 void threadTask() { std::cout << "Thread is running..." << std::endl; } private: pthread_t tid_; // 静态成员函数作为线程入口 static void* threadEntry(void* arg) { // 将void*类型的参数转换为MyClass*类型 MyClass* self = static_cast<MyClass*>(arg); // 调用非静态成员函数 self->threadTask(); return NULL; } }; int main() { MyClass obj; obj.startThread(); // 等待线程结束(这里为了简单没有等待,实际应用中可能需要join) pthread_exit(NULL); // 主线程退出,但不会结束进程,因为还有未join的线程(这里仅作示例,实际需要根据情况处理) return 0; } ``` 如果需要传递多个参数,可以定义一个结构体: ```cpp struct ThreadParams { MyClass* self; int someValue; // ... 其他参数 }; class MyClass { public: void startThread(int value) { ThreadParams* params = new ThreadParams{this, value}; // 动态分配,确保线程使用期间有效 int ret = pthread_create(&tid_, NULL, &MyClass::threadEntry, params); // ... } private: static void* threadEntry(void* arg) { ThreadParams* params = static_cast<ThreadParams*>(arg); params->self->threadTask(params->someValue); delete params; // 释放动态分配的内存 return NULL; } void threadTask(int value) { std::cout << "Value: " << value << std::endl; } }; ``` 注意事项: 1. 传递的参数(如结构体)必须确保在线程函数执行期间有效。通常我们动态分配内存(使用new),然后在线程函数中释放(delete)。 2. 如果线程函数需要返回结果,可以通过结构体传递返回指针,或者通过pthread_exit传递返回值(注意生命周期管理)。 引用说明: -C++中,普通成员函数不能直接作为线程函数,因为其隐含的this指针导致签名不匹配[^1][^5]。 - 将成员函数声明为static,并传递this指针作为参数是常见的解决方案[^1][^5]。 - 传递多个参数时,可以使用结构体将参数打包传递[^1]。 - 动态分配参数内存并在使用后释放,以避免生命周期问题[^1]。 相关问题: 1. 为什么在C++中静态成员函数可以作为pthread_create的线程函数? 2. 如何在线程函数中处理多个参数? 3. 如何确保传递给线程的参数是安全的? 4. 除了静态成员函数,还有其他方法将成员函数用作线程函数吗? 5. 如何获取线程函数的返回值?</think>### 在 C++ 中将成员函数作为 pthread_create 的线程启动函数 在 C++ 中,将类成员函数作为 `pthread_create` 的线程入口需要特殊处理,因为普通成员函数隐含 `this` 指针参数,与 `void*(*)(void*)` 函数签名不匹配。以下是完整解决方案: #### 解决方案步骤 1. **将成员函数声明为 `static`** 静态成员函数没有隐式 `this` 指针,符合 `void*(*)(void*)` 签名要求[^1][^5]。 2. **传递对象指针作为参数** 通过 `pthread_create` 的第四个参数传递 `this` 指针,用于访问非静态成员[^1][^5]。 3. **封装多参数(可选)** 如需传递额外参数,需定义参数结构体[^1]。 #### 代码实现 ```cpp #include <pthread.h> #include <iostream> class MyClass { public: void startThread() { // 创建线程并传递this指针 pthread_create(&tid, nullptr, &MyClass::threadEntry, this); } void threadTask() { std::cout << "Thread running in object: " << this << std::endl; } private: pthread_t tid; // 静态线程入口函数 static void* threadEntry(void* arg) { // 转换参数为对象指针 MyClass* self = static_cast<MyClass*>(arg); // 调用实际成员函数 self->threadTask(); return nullptr; } }; int main() { MyClass obj; obj.startThread(); pthread_exit(nullptr); // 等待子线程结束[^4] } ``` #### 多参数扩展 ```cpp struct ThreadParams { MyClass* self; // 对象指针 int extraData; // 额外参数 }; class MyClass { public: void startThread(int data) { ThreadParams* params = new ThreadParams{this, data}; // 动态分配参数 pthread_create(&tid, nullptr, &MyClass::threadEntry, params); } private: static void* threadEntry(void* arg) { ThreadParams* params = static_cast<ThreadParams*>(arg); params->self->threadTask(params->extraData); delete params; // 清理动态内存 return nullptr; } void threadTask(int data) { std::cout << "Received data: " << data << std::endl; } }; ``` #### 关键说明 1. **静态成员限制** 静态函数无法直接访问非静态成员,必须通过对象指针间接访问[^1][^5]。 2. **参数生命周期** 动态分配的参数需在线程内手动释放,避免内存泄漏[^1]。 3. **线程同步** 涉及共享数据时需使用互斥锁(如 `pthread_mutex`)同步[^4]。 4. **线程回收** 使用 `pthread_join` 或 `pthread_detach` 管理线程资源[^4]。 > 此方案通过分离函数签名要求(static 函数)和对象访问(this 指针)解决了成员函数与 POSIX 线程库的兼容性问题[^1][^3][^5]。 --- ### 相关问题 1. **为什么静态成员函数能解决 `pthread_create` 的参数匹配问题?** 2. **如何在线程函数中安全地传递多个复杂参数?** 3. **如果线程函数需要访问类的私有成员,如何实现?** 4. **使用 `pthread_create` 创建线程后,有哪些资源回收方式?** 5. **C++11 的 `std::thread` 如何简化成员函数线程的创建?**
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值