Thiết kế hàm có thể truyền được cả kiểu float* and float[]

Anh chị giải thích giúp em


Em có 1 hàm và 2 mảng như sau:

int Sentinal::findFirstPosNumb(float * const arr, int size)
{
int index = -1;
std::cout << "sizeof(arr)" << sizeof(arr) << std::endl;
for (int i = 0; i < size; i++)
{
if (arr[i] > 0) return i;
}
return index;
}

float arr0[] = { 1.2f, 2.4f, 4.4f };
float * arr1 = new float[3];
arr1[0] = -2.0f;
arr1[1] = -2.0f;
arr1[2] = 3.0f;

Nếu em truyền vào hàm arr0 thì hàm chạy sai, nếu truyền arr1 thì hàm chạy đúng.
Em mong muốn viết hàm có thể linh hoạt truyền nhiều kiểu tham số cả kiểu float* và float[] thì em nên thiết kế hàm như thế nào?

Mảng cũng chính là một con trỏ
http://cpp.sh/5rc5x
Nhấn vào nút [Run] để xem kết quả.

Mảng là con trỏ

Mình cũng chạy hàm của bạn và thấy không có gì sai cả. Truyền gì thì cũng ok.

mảng không phải là con trỏ

trong C thì mảng bị decay thành con trỏ. Để ngăn chặn điều này ở C++ thì phải truyền mảng bằng tham chiếu. Vì mảng có thể có 1 2 3 4 5… phần tử nên phải xài template để khi biên dịch C++ biết kích thước của mảng là bao nhiêu.

#include <iostream>

void func(float* f, size_t size)
{
    std::cout << "POINTER TO ARRAY\n";
    std::cout << "sizeof(f) = " << sizeof(f) << "\n"; //luôn in ra sizeof(void*)
    std::cout << "sizeof(void*) = " << sizeof(void*) << "\n";
    std::cout << "number of float elements in the array that f points to = " << size << "\n";
    std::cout << "Content of the array: ";
    for (size_t i = 0; i < size; ++i)
        std::cout << f[i] << "  ";
    std::cout << "\n";
}

template <size_t N>
void func(float (&f)[N])
{
    std::cout << "ARRAY\n";
    std::cout << "sizeof(f) = " << sizeof(f) << "\n";
    std::cout << "sizeof(void*) = " << sizeof(void*) << "\n";
    std::cout << "number of float elements in the array that f points to = " << N << "\n";
    std::cout << "Content of the array: ";
    for (size_t i = 0; i < N; ++i)
        std::cout << f[i] << "  ";
    std::cout << "\n";
}

int main()
{
    float arr[] = { 1.2f, 2.4f, 4.4f, 3.3f, 5.5f };
    float* ptr = new float[5];
    ptr[0] = -2.0f;
    ptr[1] = -2.0f;
    ptr[2] = 3.0f;
    ptr[3] = 4.0f;
    ptr[4] = -5.0f;
    
    func(arr);
    std::cout << "\n";
    func(ptr, 5);
}

output là

ARRAY
sizeof(f) = 20
sizeof(void*) = 8
number of float elements in the array that f points to = 5
Content of the array: 1.2  2.4  4.4  3.3  5.5  

POINTER TO ARRAY
sizeof(f) = 8
sizeof(void*) = 8
number of float elements in the array that f points to = 5
Content of the array: -2  -2  3  4  -5  

cú pháp truyền mảng bằng tham chiếu là <kiểu phần tử> (&arr)[N], trong đó N là kích thước của mảng mà compiler biết trước thông qua template <size_t N>.

em có thể viết ko cần template: float (&arr)[1], float (&arr)[2], float (&arr)[3], float (&arr)[4], float (&arr)[5], v.v… nhưng sẽ ko truyền được mảng ví dụ 1000 phần tử. Xài template cho nó tự động tạo mấy cái mảng có kích thước khác nhau luôn.

nếu em xài C++ thì nên xài std::array thay cho mảng C. Cú pháp dài dòng, xấu hơn nhưng tránh mấy cái array decay thành con trỏ. Còn mảng động thì em xài std::vector cho khỏi mất công quản lý bộ nhớ.

và sách nào ghi “mảng là con trỏ” thì đốt sách đó hoặc đọc lại cho kĩ câu đó viết là gì nhé.

6 Likes
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?