почему массив распадается на указатель в функции шаблона - PullRequest
7 голосов
/ 17 октября 2011

Я не понимаю, почему массив распадается на указатель в шаблонной функции.

Если вы посмотрите на следующий код: когда параметр вынужден быть ссылкой (функция f1), он не затухает. В другой функции f он разлагается. Почему тип T в функции f не const char (buff &) [3], а const char * (если я правильно понимаю)?

#include <iostream>

template <class T>
void f(T buff) {
    std::cout << "f:buff size:" << sizeof(buff) << std::endl;       //prints 4
}

template <class T>
void f1(T& buff) {
    std::cout << "f:buff size:" << sizeof(buff) << std::endl;       //prints 3
}

int main(int argc, char *argv[]) {
    const char buff[3] = {0,0,0};
    std::cout << "buff size:" << sizeof(buff) << std::endl;         //prints 3
    f(buff);
    f1(buff);
    return 0;
}

Ответы [ 6 ]

10 голосов
/ 17 октября 2011

Это потому, что массивы не могут быть переданы значением в функцию.Таким образом, чтобы заставить его работать, массив распадается на указатель, который затем передается функции по значению .

Другими словами, передача массива по значению похожа на инициализацию массива с другим массивом, но в C ++ массив не может быть инициализирован с другим массивом:

char buff[3] = {0,0,0};
char x[3] = buff; //error 

Таким образом, если массив появляется справа от =, левая сторона должна иметь тип pointer или reference:

char *y = buff; //ok - pointer
char (&z)[3] = buff; //ok - reference

Демонстрация: http://www.ideone.com/BlfSv

Это точно по той же причине auto выводится по-разному в каждом случае ниже (обратите внимание, что auto поставляется с C ++ 11):

auto a = buff; //a is a pointer - a is same as y (above)
std::cout << sizeof(a) << std::endl; //sizeof(a) == sizeof(char*)

auto & b = buff; //b is a reference to the array - b is same as z (above)
std::cout << sizeof(b) << std::endl; //sizeof(b) == sizeof(char[3])

Выход:

4 //size of the pointer
3 //size of the array of 3 chars

Демонстрация: http://www.ideone.com/aXcF5

9 голосов
/ 17 октября 2011

Поскольку массивы не могут быть переданы по значению в качестве параметра функции.
Когда вы передаете их по значению, они затухают в указателе.

В этой функции:

template <class T>
void f(T buff) {

Т не может быть char (&buff)[3], так как это ссылка.Компилятор попытался бы char (buff)[3] передать по значению, но это недопустимо.Таким образом, чтобы заставить его работать, массивы распадаются на указатели.

Ваша вторая функция работает, потому что здесь массив передается по ссылке:

template <class T>
void f1(T& buff) {

// Here T& => char (&buff)[3]
4 голосов
/ 17 октября 2011

Цитировать из спецификации, это говорит

(14.8.2.1/2) Если P не является ссылочным типом: - Если A является типом массива, тип указателя, созданный стандартным преобразованием массива в указатель (4.2) используется вместо A для вывода типа; в противном случае

Итак, в вашем случае, ясно, что,

template <class T>
void f1(T& buff) {
    std::cout << "f:buff size:" << sizeof(buff) << std::endl;       //prints 3
}

не превращается в указатель.

1 голос
/ 17 октября 2011

Причина в основном сводится к выводу типа при сопоставлении различных перегрузок. Когда вы вызываете f, компилятор выводит тип как const char[3], который затем превращается в const char*, потому что это то, что массивы делают . Это делается точно так же, как в f(1) компилятор выводит T как int, а не int&.

В случае f1, поскольку аргумент берется по ссылке, компилятор снова выводит T в значение const char[3], но принимает ссылку на него.

Ничего действительно удивительного, но скорее непротиворечивого, если бы не распад массивов на указатели при использовании в качестве аргументов функции ...

1 голос
/ 17 октября 2011

Потому что функции не могут иметь массивы в качестве аргументов. Они могут иметь ссылки на массивы.

0 голосов
/ 17 октября 2011

In f1(), Size 4 - размер указателя, который составляет 4 байта.потому что в этой функции у вас есть указатель на массив.

В f1() у вас есть этот массив по ссылке (или другому имени), и это реальный размер массива.

...