You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

带自定义删除器的unique_ptr引发目标文件警告与链接错误

问题:带自定义删除器的unique_ptr引发链接错误

场景:为大型程序生成目标文件,使用带自定义删除器的unique_ptr类型,编译命令为:

g++ -std=c++20 tmp.cpp -c -Wall

tmp.cpp代码:

#include <memory>

using specialptr = std::unique_ptr<int, decltype([](int *f) {
                     delete f;
                   })>;

specialptr fun(){ 
  return specialptr{new int};
}

编译tmp.cpp时出现警告:

tmp.cpp:12:12: warning: ‘specialptr fun()’ defined but not used [-Wunused-function]
12 | specialptr fun(){ return specialptr{new int};}
|

将该目标文件与调用fun()的main.cpp链接时,出现错误:

In file included from main.cpp:1:
tmp.h:19:12: warning: ‘specialptr fun()’ used but never defined
19 | specialptr fun();
| ^~~
/usr/bin/ld: /tmp/ccnuTTGC.o: in function main': main.cpp:(.text+0x4c): undefined reference to fun()'
collect2: error: ld returned 1 exit status

将返回值改为普通指针时代码可正常运行,但已在头文件中声明类型与函数,请问问题出在哪里?使用g版本:g (Ubuntu 11.3.0-1ubuntu1~22.04) 11.3.0


问题原因与解决方法

核心原因

C++中每个lambda表达式的类型都是唯一的匿名类型。你在tmp.cpp中用decltype([](int* f){delete f;})定义的specialptr类型,和main.cpp通过头文件引入的specialptr类型(若头文件采用相同lambda写法)是完全不同的类型。这导致fun()在tmp.cpp中的函数签名(返回自定义specialptr)与main.cpp中声明的签名不匹配,链接器无法找到对应函数实现,从而报"undefined reference"错误。

而普通指针int*是标准类型,所有翻译单元中的类型完全一致,函数签名匹配,因此链接正常。

解决办法

方法1:使用具名函数/函数指针作为删除器类型

将删除器改为普通函数,用函数指针类型作为unique_ptr的模板参数,确保所有翻译单元类型一致:

// tmp.h
#include <memory>

void custom_deleter(int* f) { delete f; }
using specialptr = std::unique_ptr<int, void(*)(int*)>;

specialptr fun();
// tmp.cpp
#include "tmp.h"

specialptr fun(){ 
  return specialptr{new int, custom_deleter};
}

方法2:使用inline变量共享lambda类型

将lambda定义为inline全局变量,确保所有翻译单元共享同一个lambda实例,其decltype类型也会一致:

// tmp.h
#include <memory>

inline auto deleter = [](int* f) { delete f; };
using specialptr = std::unique_ptr<int, decltype(deleter)>;

specialptr fun();
// tmp.cpp
#include "tmp.h"

specialptr fun(){ 
  return specialptr{new int, deleter};
}

方法3:使用std::function封装删除器

用std::function作为删除器类型,它是通用的可调用对象包装器,能统一不同实现的类型:

// tmp.h
#include <memory>
#include <functional>

using specialptr = std::unique_ptr<int, std::function<void(int*)>>;

specialptr fun();
// tmp.cpp
#include "tmp.h"

specialptr fun(){ 
  return specialptr{new int, [](int* f){delete f;}};
}

内容的提问来源于stack exchange,提问作者Trick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 09:41:02