簡體   English   中英

在沒有明確數組大小的情況下將數組傳遞給 function

[英]Passing an array to function without explicit array size

我是 C++ 的新手,關於將 arrays 傳遞給 function (可能是同一件事),我有 2 個問題。

  1. 通過引用將數組傳遞給 function 時,參數是否不需要顯式大小信息,如void my_func (const T &array)而不是void my_func (const T (&array)[10])

  2. 具有數組指針參數void my_func (const T* array)void my_func (const T(* array)[10]) (有或沒有明確的數組大小)的 function 有什么區別?

下面是在不顯式傳遞數組大小的情況下接受任何大小的數組的代碼:

template<typename _Ret, //return type
         typename _Coll> //collection type, no size argument
_Ret Sum(const _Coll& c) {

        _Ret sum = 0;
        for (auto& v : c)
                sum += v;
        return sum;
}

int main() {
        // With regular array, Passed as reference
        int arr[] = {1, 2, 3, 4, 5};
        std::cout << Sum<int64_t>(arr) << "\n"; //15

        // With vector 
        std::vector<int> vec = {1, 2, 3, 4, 5};
        std::cout << Sum<int64_t>(vec) << "\n"; //15
        return 0;
}

此示例源自的文章如下所述:

此外,模板的使用甚至可以避免難看的數組引用語法,並使代碼適用於任何數組大小。

如果這可行,那么以下任何數組大小的通用模板是否不必要?

template<typename T, std::size_t S>
void my_func(T (&arr)[S]) {
        ... ...;
}

還有一個附帶問題,為什么template<typename _Ret, typename _Coll>需要 2 個模板 arguments 但Sum<int64_t>(arr)只指定 1 個模板參數?

  1. 通過引用將數組傳遞給 function 時,參數是否不需要顯式大小信息,如 void my_func (const T &array) 而不是 void my_func (const T (&array)[10])?

引用參數不一定必須是對數組的引用。

const T &是對const T的引用。 例如,如果T類型別名為int[10] ,則const T &const int (&)[10]即引用 10 const int的數組。 如果T是模板類型參數,那么模板可以被實例化為不同的類型,包括不同大小的數組類型,也包括非數組類型。

const T (&)[10]是對 10 個const T數組的引用。

當大小信息被編碼在參數的類型中時,您不需要單獨傳遞大小信息,例如參數是對數組的引用時的情況。

但是我的問題中的示例既沒有定義別名

你錯了。 您的示例是模板 function,模板類型參數類型別名。

Function 調用語句只是將 arr 轉換(衰減)為指向 int 的指針。

你錯了。 當引用綁定到它時, arr不會衰減為指向 int 的指針。 數組衰減發生在左值到右值的轉換上。 將引用綁定到 object 時,沒有此類轉換。


  1. 具有數組指針參數 void my_func (const T* array) 和 void my_func (const T(* array)[10])(帶或不帶顯式數組大小)新版本的 function 有什么區別?

const T*是指向const T的指針。

const T(*)[10]是指向const T[10]的指針,即指向 10 T數組的指針。 例如,如果Tint的別名,則前者為const int* ,后者為const int(*)[10]

注意,如果T是一個數組,那么前者也可以是一個指向數組的指針。 例如,如果Tint[42] ,那么前者是const int(*)[42]即指向 42 個const int數組的指針,而后者是const int(*)[42][10]即指向一個42 個const int的 10 個 arrays 的數組。

...和 void my_func (const T* array[10])(有或沒有明確的數組大小)舊版本

const T* array[10]是一個包含 10 個指向const T的指針的數組。 但是,function 參數絕不是 C++ 中的數組。 如果使用數組參數聲明 function,則將該參數調整為指向該數組元素的指針。 指向 const T 的 10 個指針數組的元素是指向const T const T的指針,即const T* ,指向此類 object 的指針是const T** 因此,這個參數實際上是const T**

const T*const T**之間的區別在於后者是指向前者的指針。

如果這可行,那么以下任何數組大小的通用模板是否不必要?

這取決於。 如果您不需要它,那么您的用例就不需要它。

但這並不意味着它完全沒有必要。 For example, if you need a function overload that accepts only arrays, then you cannot use a T& parameter which can accept arguments that are not arrays.

為什么template<typename _Ret, typename _Coll>需要 2 個模板 arguments

因為T (&arr)[S] S的 S 必須是模板值參數,才能將引用綁定到任何大小的 arrays。 如果您使用諸如T (&arr)[10]之類的非變量常量,那么您只能接受一種大小的 arrays。

但是Sum<int64_t>(arr)僅指定 1 個模板參數?

這個不使用對S元素數組的引用,因此不需要模板值參數S


_Ret_Coll名稱保留給語言實現。 通過將這些名稱定義為模板參數,程序的行為將是未定義的。 不要定義保留名稱。 您應該為模板參數選擇其他名稱。

  1. 假設T不是一個數組, void my_func (const T &array)不會是嘗試的正確方法,因為它需要一個對T的引用,而不是一個數組。 測試這個的正確方法可能是void my_func(const T (&array)[])
#include <iostream>

void my_func(const int (&)[]) {}

int main()
{
    int a = 10;
    int b[] = {1, 2, 3};
    my_func(b);

    return 0;
}

當我嘗試運行它時,我收到一個錯誤: error: parameter '<anonymous>' includes reference to array of unknown bound 'const int []' const int (&)[3]替換const int (&)[] ] 使其工作。 所以不,你必須指定數組的大小。


  1. 這是兩個完全不同的東西。 void my_func(const T *array)等價於void my_func(const T array[])void my_func(const T (*array)[10])等價於void my_func(const T array[][10])

C++ Insights是查看模板如何擴展的好地方。 當我們執行Sum<int64_t>(arr)時, Sum的新 function 將從int64_t Sum<int64_t, int [5]>(int const (&c)[5])模板創建。 如您所見,您現在不必指定尺寸,因為模板會為您完成。 每次將不同大小的數組傳遞給Sum時,都會創建一個新的 function 以使用該大小。

還有一個附帶問題, template<typename _Ret, typename _Coll>需要 2 個模板 arguments 但為什么does Sum<int64_t>(arr)只指定 1 個模板參數?

因為推導出了第二個參數。 由於編譯器知道您將int [5]傳遞給 function,因此您無需傳遞類型。 但是,它無法知道返回類型,因此您必須傳遞它的類型。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM