使用this online compiler构建,代码如下:
aldeed:tabular
输出:
#include <iostream>
#include <type_traits>
#include <tuple>
int main() {
std::cout << std::is_trivially_copyable<std::tuple<int>>::value << std::endl;
std::cout << std::is_trivially_copyable<std::pair<int, int>>::value << std::endl;
std::cout << std::is_trivial<std::tuple<int>>::value << std::endl;
std::cout << std::is_trivial<std::pair<int, int>>::value << std::endl;
return 0;
}
我在Visual Studio 2015中获得了相同的结果。
为什么会这样?是否有正当理由0
0
0
0
POD类型,更不用说简单的std::tuple
,不能轻易复制?我假设它们的实现提供了一些自定义赋值运算符,但它们与编译器生成的默认版本有何不同?
答案 0 :(得分:9)
就简单的可复制性而言,pair
的问题是标准不会要求复制/移动赋值运算符是微不足道的。该标准明确声明复制/移动构造函数是默认的,但对于赋值则不然。实现也可以默认它们,但标准不要求它。
标准并不是很合理的原因。但它没有。
对于tuple
,事情是很多更复杂。许多tuple
实现基于具有正确大小/对齐的存储缓冲区,并使用放置new
来构造该缓冲区内的各个成员。这一切都很好,但是这种类型必须实现手动复制/移动构造函数,因为它必须调用每种类型的复制/移动构造函数。即使它知道它们都是可以复制的并且通过memcpy
复制它们,这仍然是一个手动操作。而这使它无法从琐碎的可复制性中取消资格。
现在,有tuple
的实现,如果类型可以轻易复制,则可以轻松复制。但是没有要求以这种方式实现它们。如果所有类型都可以轻松复制,那么它会使tuple
实现非常复杂,要求它们以一种方式实现它们,否则以不同的方式实现它们。
答案 1 :(得分:6)
因为std::tuple
具有复制/移动ctor和赋值运算符,所以它使该类不可复制。
请参阅cpp reference:
一个简单的可复制类是
的类Has no non-trivial copy constructors (this also requires no virtual functions or virtual bases) Has no non-trivial move constructors Has no non-trivial copy assignment operators Has no non-trivial move assignment operators Has a trivial destructor
但是std::tuple
具有上述所有构造函数和赋值运算符。