如何找到副本的来源

How can I find the source of a copy?

本文关键字:副本 何找      更新时间:2023-10-16

我有一些使用容器的代码让我感到悲伤。问题是我想在其中一个子字段中放置一个智能指针 (unique_ptr)。例如:

struct subrecord {
    int id;
    int handle;
    std::list<std::unique_ptr<some_really_big_record>> update; // <-- Problem field
};
struct database {
    std::map <std::string, subrecord> name_subrec_map;
    std::vector <std::string> a_names;
    std::vector <std::string> b_names;
};

一切都编译得很好,直到我尝试添加该update字段。一旦我这样做了,编译器就开始抱怨该unique_ptr没有可用的复制运算符。这很公平,它不应该有一个。无论如何,我并不打算复制这些地图条目。

但是,编译器没有告诉我这个副本在我的代码中来自哪里。到现在为止,已经相当多了。有什么好方法可以说吗?我尝试搜索对updatename_subrec_map的引用并将它们注释掉,但根本没有任何运气。唯一可以消除错误的方法是注释掉该字段本身update

我不想切换到shared_ptr,只是因为我找不到当副本。

如果您的代码在某处复制子记录,则它可能隐藏在您的错误消息中。

由于子记录是可移动的,但不可复制,因此您可以将其放在其标题中:

 struct subrecord 
 { 
       // ...
       subrecord( const subrecord & ) = delete;
       subrecord( subrecord&& ) = default;
 };

您甚至可以暂时注释掉列表成员,并查看在调用此副本的位置是否出现任何编译器错误。

注意:

如果您的编译器不支持删除和默认值,请将复制构造函数设为私有,但您还必须将移动构造函数设为公共。

如果这只是查找编译器错误的临时措施,则可以跳过实现它,因为您不关心链接错误。稍后将删除它,但还必须删除私有复制构造函数。

尽管您最好实现它,因为这将暴露代码中复制子记录的任何进一步尝试,而不会给任何敢于这样做的人编译器错误消息地狱。