2016-08-05 64 views
8

建有this online compiler,下面的代码:为什么不能std :: tuple <int>可以复制?

#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; 
} 

输出:

0 
0 
0 
0 

我得到与Visual Studio相同的结果,2015年

为什么是这样呢?是否有POD类型的std::tuple的有效理由,更不用说简单的std::pair,不能简单地复制?我认为他们的实现提供了一些自定义赋值操作符,但它们与编译器生成的默认版本有什么不同?

+1

http://stackoverflow.com/questions/36625317/error-cannot-pass-objects-of-non-trivially-copyable-type-through意味着该标准不需要它,所以实现不打扰 – happydave

回答

7

只要琐碎的可复制性涉及pair就是标准不要求复制/移动赋值运算符是平凡的。该标准明确声明,复制/移动构造函数是默认的,但对于作业不是这样。一个实现也可以默认它们,但标准并不要求它。

没有真正的理由为什么标准不需要它。但事实并非如此。

对于tuple,东西是很多更复杂。许多tuple实现基于具有正确大小/对齐的存储缓冲区,并且使用位置new来构建该缓冲区内的各个成员。这一切都很好,但这样的类型必须实现手动复制/移动构造函数,因为它必须调用每种类型的复制/移动构造函数。即使它知道它们都是可复制的并通过memcpy复制它们,但这仍然是一个手动操作。这使它不能享受​​微不足道的可复制性。

现在,有tuple的实现,如果类型是可复制的,它们可以是可复制的。但是没有要求以这种方式实现它们。如果所有类型都是可复制的,并且以其他方式以不同的方式实现它们,那么要求它们实现它们自己的一种方式会使得实现变得复杂。

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具有以上所有的构造函数和赋值运算符。

+0

没有证明元组的特殊成员函数是非平凡的,答案并不完整。 –

+1

通过定义[std :: tuple](http://en.cppreference.com/w/cpp/utility/tuple)的copy/move ctors/assignments,它已经意味着这样的ctors /操作符不是微不足道的。 – Mine

相关问题