为什么 std::tuple 不能<int>被简单复制?
Why can't std::tuple<int> be trivially copyable?
使用此在线编译器构建,以下代码:
#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
,不能被琐碎地复制,有什么正当的理由吗?我认为它们的实现提供了一些自定义赋值运算符,但它们与编译器生成的默认版本有何不同?
就琐碎的可复制性而言,让pair
头疼的是,标准不要求复制/移动赋值运算符是琐碎的。该标准明确声明复制/移动构造函数是默认的,但对于赋值则不是这样。一个实现也可以默认它们,但标准并不要求这样做
没有什么好的理由可以解释为什么标准不要求它。但它没有。
对于tuple
来说,事情要复杂得多。许多tuple
实现基于具有合适大小/对齐的存储缓冲区,并使用放置new
来构造该缓冲区内的各个成员。这一切都很好,但这样的类型必须实现手动复制/移动构造函数,因为它必须调用每个类型的复制/移动构造器。即使它知道它们都是微不足道的可复制性,并通过memcpy
复制它们,这仍然是一个手动操作。这使它失去了微不足道的可复制性。
现在,有一些tuple
的实现,如果类型是平凡可复制的,那么它们可能是平凡可拷贝的。但没有要求以这种方式来实施它们。如果所有类型都是可复制的,那么要求它们以一种方式实现自己,而在其他情况下以不同的方式实现它们,这将使tuple
实现非常复杂。
因为std::tuple
具有复制/移动ctor和赋值运算符,所以它使类不具有可复制性。
参见cpp参考:
一个微不足道的可复制类是
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
具有以上所有的构造函数和赋值运算符。
相关文章:
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 在C++程序中输入的文本文件将不起作用,除非文本被复制和粘贴
- 使用strcpy将char数组的元素复制到另一个数组
- 是否可以初始化不可复制类型的成员变量(或基类)
- 为什么在C++中使用私有复制构造函数与删除复制构造函数
- C++ Windows 驱动程序MSB3030无法复制该文件,因为它找不到
- 复制列表初始化的隐式转换的等级是多少
- 当从函数参数中的临时值调用复制构造函数时
- 有可能在Armadillo中复制MATLAB circshift方法吗
- 复制几乎为空的数组的最快方法
- 以下示例中如何避免代码复制?C++/库达
- 如果有一个模板构造函数只有一个泛型参数,为什么我必须有一个复制构造函数
- 为什么需要复制构造函数,在哪些情况下它们非常有用
- 不能将复制初始化与隐式转换的多个步骤一起使用
- 当有分配器意识的容器被复制/移动时,反弹分配器是否被复制/移走
- 为什么复制而不是移动数据元素?
- 文件系统:复制功能的速度秘诀是什么
- 使用仅使用一次的变量调用的复制构造函数.这可能是通过调用move构造函数进行编译器优化的情况吗
- EASTL矢量<向量<int>>连续的
- std::vector<;uint8_t>;当C++11/14启用时,手动复制而不是调用memcpy