C++11の新しい容器(array,無秩序容器,tupleメタグループ)
30869 ワード
文書ディレクトリ shrink_to_fit array forward_list 無秩序容器 ユニットtuple tuple の定義と初期化 tupleメンバー へのアクセス tupleのメンバー数とメンバータイプ 合併tuple tuple を巡る C++11実現tupleの遍歴 C++14/17 を巡る参考資料 shrink_to_fit
上から分かるように、VS下ではvector拡張が1.5倍(Linux下では2倍).拡張後、49*sizeof(int)の不要メモリが多くなったため、C++11はshrink_を提供したto_fit関数はこの部分のメモリを解放しますが、この関数は要求にすぎず、必ずしも成功するとは保証されません.
C++11以前はclear()関数がパージ容器内の要素の個数であることが知られていたが、メモリは解放されていなかったので、一般的にはswap関数で解放されていたが、clear後にshrink_to_fit関数を使用してメモリを解放します.
array
この容器を導入した目的はC中の配列を置き換えることであり,C中の配列は安全検査をしていないため,C++はこの定長容器を提供した.C++STLとの互換性のためにも、従来のCと互換性のある汎用関数begin()とend()関数が提供されているが、arrayはより規範的である.
forward_list
listは双方向チェーンテーブルでforward_Listは一方向チェーンテーブルであり,効率が高いため,容器にsize()メソッドを提供していない容器である.
むじゅんようき
mapとsetの下層はいずれも赤黒樹によって実現され,その検索/増加/削除の時間的複雑さはO(log(n))であり,この2つの容器は秩序化されており,すなわち要素がサポートされる
C++11はunordered_を提供しますmap/setは,その下層がハッシュテーブルによって実現されるので,時間的複雑度はいずれもO(1)であり,無秩序である.
メタグループtuple
ジルコニウムtupleはpairのテンプレートに似ている.各pairのメンバータイプは異なりますが、pairには2人のメンバーしかいません.1つのtupleには任意の数のメンバーがいます.各決定されたtupleタイプのメンバー数は固定されているが、1つのtupleタイプのメンバー数は別のtupleタイプと異なることができる.次はtupleがサポートする操作です.
tupleの定義と初期化
私たちがtupleに登ったとき、各メンバーのタイプを指摘する必要があります.
tupleオブジェクトを作成する場合は、tupleのデフォルトのコンストラクション関数を使用して、各メンバーの値を初期化できます.someValのように、各メンバーに初期値を明示的に指定することもできます.tupleという構造関数はexplicitなので,直接初期化しなければならない.
類似make_pair関数、標準ライブラリにもmake_が用意されていますtupleオブジェクトを生成するtuple関数:
tupleメンバーへのアクセス
pairには2つのメンバーしかいないのでfirstとsecondでアクセスできますが、tupleのメンバーは固定されていないので、メンバーを設定してアクセスすることはできません.tupleのメンバーにアクセスするには、標準ライブラリ関数テンプレートgetを使用します.getを使用するには、いくつかのメンバーにアクセスしたいことを示す明示的なテンプレートの実パラメータを指定する必要があります.getにtupleオブジェクトを渡し、指定したメンバーの参照を返します.
はtieによって解包することもできる:
パケットを解く場合、ある位置の値だけを解く場合はstd::ignoreプレースホルダで、ある位置を理解できない値を表すことができます.
C++14は、タイプによってtupleメンバーを取得できます.
tuple内のメンバーの数とメンバータイプ
クラステンプレートtuple_size::valueは、与えられたtupleタイプのメンバーの数を取得し、decltypeによってtupleTypeを取得することができる.
はクラステンプレートtuple_を介してもよいElement::tupleタイプで指定したメンバーのタイプを取得するtype:
マージtuple
ゞ 可以通过tuple_ゞcatは2つのtupleを結合する.
tupleを巡る
以上のコード、すなわちパラメータ伝達方式による非タイプテンプレートパラメータの付与は、コンパイルが通過しない.getパラメータは、コンパイル時に定数式である必要があります.
C++11 tupleの遍歴を実現
C++14/17遍歴
ここは空いてから補充します.
参考資料
(1)『C++Primer』(2)『クイックハンドC++11/14』(3)https://blog.csdn.net/yockie/article/details/89511498
// VS2019
int main() {
vector<int> arr(100);
arr.emplace_back(10);
cout << arr.size() << endl; // 101
cout << arr.capacity() << endl; // 150
arr.shrink_to_fit();
cout << arr.size() << endl; // 101
cout << arr.capacity() << endl; // 101
arr.swap(vector<int>());
cout << arr.size() << endl; // 0
cout << arr.capacity() << endl; // 0
}
上から分かるように、VS下ではvector拡張が1.5倍(Linux下では2倍).拡張後、49*sizeof(int)の不要メモリが多くなったため、C++11はshrink_を提供したto_fit関数はこの部分のメモリを解放しますが、この関数は要求にすぎず、必ずしも成功するとは保証されません.
C++11以前はclear()関数がパージ容器内の要素の個数であることが知られていたが、メモリは解放されていなかったので、一般的にはswap関数で解放されていたが、clear後にshrink_to_fit関数を使用してメモリを解放します.
array
この容器を導入した目的はC中の配列を置き換えることであり,C中の配列は安全検査をしていないため,C++はこの定長容器を提供した.C++STLとの互換性のためにも、従来のCと互換性のある汎用関数begin()とend()関数が提供されているが、arrayはより規範的である.
int main() {
constexpr int size = 10;
array<int, size> arr{ 1, 2, 5, 3, 5, 1 };
sort(arr.begin(), arr.end());
}
forward_list
listは双方向チェーンテーブルでforward_Listは一方向チェーンテーブルであり,効率が高いため,容器にsize()メソッドを提供していない容器である.
むじゅんようき
mapとsetの下層はいずれも赤黒樹によって実現され,その検索/増加/削除の時間的複雑さはO(log(n))であり,この2つの容器は秩序化されており,すなわち要素がサポートされる
C++11はunordered_を提供しますmap/setは,その下層がハッシュテーブルによって実現されるので,時間的複雑度はいずれもO(1)であり,無秩序である.
メタグループtuple
ジルコニウムtupleはpairのテンプレートに似ている.各pairのメンバータイプは異なりますが、pairには2人のメンバーしかいません.1つのtupleには任意の数のメンバーがいます.各決定されたtupleタイプのメンバー数は固定されているが、1つのtupleタイプのメンバー数は別のtupleタイプと異なることができる.次はtupleがサポートする操作です.
tupleの定義と初期化
私たちがtupleに登ったとき、各メンバーのタイプを指摘する必要があります.
tuple<int, double, size_t> threeD; // 0
tuple<string, vector<double>, list<int>> someVal("constants", { 3.15,22 }, { 0,1 });
tupleオブジェクトを作成する場合は、tupleのデフォルトのコンストラクション関数を使用して、各メンバーの値を初期化できます.someValのように、各メンバーに初期値を明示的に指定することもできます.tupleという構造関数はexplicitなので,直接初期化しなければならない.
類似make_pair関数、標準ライブラリにもmake_が用意されていますtupleオブジェクトを生成するtuple関数:
auto item = make_tuple("hello", 3, 3.0); // item tuple
tupleメンバーへのアクセス
pairには2つのメンバーしかいないのでfirstとsecondでアクセスできますが、tupleのメンバーは固定されていないので、メンバーを設定してアクセスすることはできません.tupleのメンバーにアクセスするには、標準ライブラリ関数テンプレートgetを使用します.getを使用するには、いくつかのメンバーにアクセスしたいことを示す明示的なテンプレートの実パラメータを指定する必要があります.getにtupleオブジェクトを渡し、指定したメンバーの参照を返します.
auto item = make_tuple("hello", 3, 3.0); // item tuple
auto book = get<0>(item); // item
はtieによって解包することもできる:
int main() {
auto item = make_tuple("hello", 3, 3.0); // item tuple
using type = decltype(item);
tuple_element<0, type>::type x; //
tuple_element<1, type>::type y;
tuple_element<2, type>::type z;
tie(x, y, z) = item;
cout << x << " " << y << " " << z << endl; // hello,3, 3
}
パケットを解く場合、ある位置の値だけを解く場合はstd::ignoreプレースホルダで、ある位置を理解できない値を表すことができます.
tie(x, ignore, ignore) = item; // , y z
C++14は、タイプによってtupleメンバーを取得できます.
int main() {
auto item = make_tuple("hello", 3, 3.0); // item tuple
using type = decltype(item);
cout << get<int>(item) << endl; // 3
cout << get<double>(item) << endl; // 3
cout << get<const char*>(item) << endl; // hello
}
tuple内のメンバーの数とメンバータイプ
クラステンプレートtuple_size::valueは、与えられたtupleタイプのメンバーの数を取得し、decltypeによってtupleTypeを取得することができる.
はクラステンプレートtuple_を介してもよいElement::tupleタイプで指定したメンバーのタイプを取得するtype:
int main() {
auto item = make_tuple("hello", 3, 3.0); // item tuple
auto book = get<0>(item); // item
using type = decltype(item);
size_t sz = tuple_size<type>::value;
cout << sz << endl; // 3
tuple_element<1, type>::type cnt = get<1>(item); // cnt int
}
マージtuple
ゞ 可以通过tuple_ゞcatは2つのtupleを結合する.
tupleを巡る
template<typename... Args>
std::ostream& operator<<(std::ostream& os, const std::tuple<Args...>& t)
{
os << "(" << std::get<0>(t);
for (size_t i = 1; i < sizeof...(Args) << ++i)
os << ", " << std::get<i>(t);
return os << "]";
}
int main(int, char**)
{
cout << make_tuple("InsideZhang", 23, "HeNan") << endl;
// , i
return 0;
}
// :
template<typename Tuple>
void tuple_print(const Tuple& t, size_t N, std::ostream& os)
{
if (N != 1)
tuple_print(t, N-1, os);
os << std::get<N-1>(t);
}
以上のコード、すなわちパラメータ伝達方式による非タイプテンプレートパラメータの付与は、コンパイルが通過しない.getパラメータは、コンパイル時に定数式である必要があります.
C++11 tupleの遍歴を実現
template<typename Tuple, size_t N>
struct tuple_print {
static void print(const Tuple& t, ostream& os) {
tuple_print<Tuple, N - 1>::print(t, os);
os << ", " << get<N - 1>(t);
}
};
//
template<typename Tuple>
struct tuple_print<Tuple, 1> {
static void print(const Tuple& t, ostream& os) {
os << "(" << get<0>(t);
}
};
// operator<<
template<typename... Args>
ostream& operator << (ostream & os, const tuple<Args...> & t) {
tuple_print<decltype(t), sizeof...(Args)>::print(t, os);
return os << ")";
}
int main() {
auto t1 = std::make_tuple("InsideZhang", 23, "HeNan");
auto t2 = std::make_tuple("InsideLi", 23, "AnHui");
cout << std::tuple_cat(t1, t2) << endl;
// (InsideZhang, 23, HeNan, InsideLi, 23, AnHui)
}
C++14/17遍歴
ここは空いてから補充します.
参考資料
(1)『C++Primer』(2)『クイックハンドC++11/14』(3)https://blog.csdn.net/yockie/article/details/89511498