我試圖了解 std::array 建構式的作業原理以及他如何獲取陣列并將其初始化為陣列。
我正在搜索標準庫檔案,我找到了這段代碼
#if _HAS_CXX17
template <class _First, class... _Rest>
struct _Enforce_same {
static_assert(conjunction_v<is_same<_First, _Rest>...>,
"N4687 26.3.7.2 [array.cons]/2: "
"Requires: (is_same_v<T, U> && ...) is true. Otherwise the program is ill-formed.");
using type = _First;
};
template <class _First, class... _Rest>
array(_First, _Rest...) -> array<typename _Enforce_same<_First, _Rest...>::type, 1 sizeof...(_Rest)>;
#endif // _HAS_CXX17
這是建構式嗎?它是如何作業的?
謝謝!
uj5u.com熱心網友回復:
正如在上面的評論中已經提到的,std::array是聚合型別,因此您不是在呼叫建構式,而是在實際初始化資料成員。
您在問題中指向的代碼允許在std::array不說明陣列型別和大小的情況下創建。這是通過扣除指南完成的,如下面的代碼所示。
如果您自己實作它,它的外觀如下:
template<typename T, std::size_t SIZE>
struct MyArray {
T arr[SIZE];
};
// MyArray deduction guides:
// similar code was added to std::array in C 17 to allow the
// creation of a2 below, without providing template arguments
template <class _First, class... _Rest>
MyArray(_First, _Rest...) -> MyArray<_First, 1 sizeof...(_Rest)>;
int main() {
MyArray<int, 5> a1 = {1, 2, 3}; // since C 11
MyArray a2 {1, 2, 3}; // deduced to MyArray<int, 3>, since C 17
// creation of a2 is based on the deduction guides above
}
上面的代碼忽略了向 MyArray 發送不同型別的情況,如下所示:
MyArray a2 {1, 2.0, 3}; // still deduced to MyArray<int, 3> with our code
有幾個選項可以處理上述問題:決定陣列的型別基于第一個值的型別(正如我們在我們的幼稚實作中實際所做的那樣),決定型別將基于值的common_type,或禁止這樣的初始化。C 標準決定禁止它,因此需要檢查所有型別是否相同,如果不同則引發編譯錯誤,例如使用static_assert. 正如在發布的原始代碼中所做的那樣,使用_Enforce_same結構。
內部資料成員的初始化基于聚合初始化,發送到結構的值被傳遞到其欄位中,如下例所示:
struct A {
int a;
};
struct B {
int a, b;
};
struct C {
int a[5];
};
int main {
A a = {1}; // goes to a.a
B b = {1, 2}; // goes to b.a and b.b
C c = {1, 2, 2}; // goes into the array c.a
}
uj5u.com熱心網友回復:
@Amir Kirsh 的回答非常詳細。所以我不想重復。相反,我邀請您查看以下代碼的匯編輸出:
#include <iostream>
#include <array>
int main( )
{
// std::array<int, 5> arr = { 1, 2, 3 }; // std::array
int arr[5] { 1, 2 , 3 }; // raw array (aka C-style array)
for ( const auto& i : arr )
{
std::cout << i << '\n';
}
return 0;
}
您可以在此處檢查和比較兩個陣列的匯編代碼 。
只需取消對版本的注釋并注釋掉原始陣列版本即可查看該版本的匯編代碼。std::arraystd::array
但為了讓您的作業更輕松,以下是兩個陣列的代碼:
std::array
mov rax, QWORD PTR .LC0[rip]
mov QWORD PTR [rsp 28], 0
lea rbx, [rsp 16]
lea rbp, [rsp 36]
mov QWORD PTR [rsp 16], rax
mov DWORD PTR [rsp 24], 3
raw array
mov rax, QWORD PTR .LC0[rip]
mov QWORD PTR [rsp 28], 0
lea rbx, [rsp 16]
lea rbp, [rsp 36]
mov QWORD PTR [rsp 16], rax
mov DWORD PTR [rsp 24], 3
是的!可以看出,它們是相同的。將在編譯時std::array轉換為其等效的C 樣式陣列。這只是語法糖。實際上不需要建構式或解構式。兩者都是一樣的東西,都存盤在堆疊上。它們是可簡單構造的,這意味著它們可以通過遞增堆疊指標暫存器和其他一些快速指令來構造。
像這樣:
#include <iostream>
#include <type_traits>
#include <array>
int main( )
{
std::cout << std::boolalpha << "Is std::array<int, 5> trivially constructible: "
<< std::is_trivially_constructible< std::array<int, 5> >::value << '\n';
std::cout << std::boolalpha << "Is int[5] trivially constructible: "
<< std::is_trivially_constructible< int[5] >::value << '\n';
結果:
Is std::array<int, 5> trivially constructible: true
Is int[5] trivially constructible: true
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/387774.html
上一篇:實作WASM文本格式的結構體
