我想知道是否有一种简单的方法可以通知STL容器本身何时被复制或移动(无需处理修改或尝试重载STL方法的复杂性 - 因为我认为这很麻烦)。
当我调试单线程应用程序时,我使用简单的std::cout
输出来通知移动和副本(确保我自己的引用类型符合我的意图)。
我已经考虑了一段时间,而且我只生成了真正的,非常愚蠢的想法(比如重载std :: move来生成实际的代码,以便它通知所有创建候选人的尝试移动 - 哈哈)。或者你可能重载真正的STL移动和复制构造函数,然后让它们调用真实的?
我认为这对于了解正在发生的复制精确位置,实际上正在移动的位置(如果类型为常量时不会衰减到复制操作)非常有用。
任何见解都会很有趣并且值得赞赏。
答案 0 :(得分:4)
没有良好的方法来做到这一点。 HeroicKatora's comment是我所知道的唯一可能性:构建一个自定义分配器,在复制构造和移动构造时打印出消息。但是有问题......
要构建自定义分配器,请随时使用我的allocator boilerplate(无需版权,参考或链接)。这只是一个骨架分配器,可以帮助您入门。它没有什么特别的。
我用这个来为这个问题创建以下稻草人分配器:
template <class T>
class allocator
{
public:
using value_type = T;
allocator() = default;
allocator(allocator const&) = default;
allocator(allocator&&)
{
std::cout << "container move construction\n";
}
template <class U> allocator(allocator<U> const&) noexcept {}
value_type* // Use pointer if pointer is not a value_type*
allocate(std::size_t n)
{
return static_cast<value_type*>(::operator new (n*sizeof(value_type)));
}
void
deallocate(value_type* p, std::size_t) noexcept // Use pointer if pointer is not a value_type*
{
::operator delete(p);
}
allocator
select_on_container_copy_construction() const
{
std::cout << "container copy construction\n";
return *this;
}
};
template <class T, class U>
bool
operator==(allocator<T> const&, allocator<U> const&) noexcept
{
return true;
}
template <class T, class U>
bool
operator!=(allocator<T> const& x, allocator<U> const& y) noexcept
{
return !(x == y);
}
当容器副本构造时,需要调用std::allocator_traits<your_allocator>::select_on_container_copy_construction()
来获取复制构造容器的分配器。如果未在分配器中实现此功能,std::allocator_traits
只返回分配器的副本。我已经重写了这个默认行为以输出消息。
当容器移动构造时,需要移动构造分配器。所以我修改了allocator
移动构造函数来打印出一条消息。
使用这种方法的问题是没有要求容器只移动或复制你的分配器一次!
使用vector
作为示例容器,gcc为此驱动程序提供了理想的结果:
template <class T> using vector = std::vector<T, allocator<T>>;
template <class T> using deque = std::deque<T, allocator<T>>;
int
main()
{
vector<int> v;
std::cout << "Begin move\n";
auto v2 = std::move(v);
std::cout << "End move\n";
std::cout << "Begin copy\n";
auto v3 = v2;
std::cout << "End copy\n";
}
gcc输出:
Begin move
container move construction
End move
Begin copy
container copy construction
End copy
Visual Studio为副本添加了一个无偿的移动构造:
Begin move
container move construction
End move
Begin copy
container copy construction
container move construction
End copy
LLVM的libc ++在移动结构上加倍:
Begin move
container move construction
container move construction
End move
Begin copy
container copy construction
container move construction
container move construction
End copy
总之,一种令人不满意的“种类”。 : - \