Как сделать передачу массива по ссылке необязательной в функции С++?

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

У меня есть такая функция:

void foo(int (&arr) [3])
{
    //some code...
}

Затем я попробовал это:

void foo(int (&arr) [3] = nullptr)
{
    //some code...
}

но это явно не сработало, потому что ссылка не может быть nullptr и это даже не массив.

Обновлено: Я хотел бы не использовать std::array, если это возможно, и мне также нужно знать размер передаваемого массива, не передавая его размер, поэтому я этого не сделал: int (*arr)[3].

Вероятно, проще написать отдельную перегрузку foo, которая не принимает аргумент.

Nathan Pierson 18.06.2023 17:13

Передать указатель int (*arr)[3] = nullptr?

Evg supports Moderator Strike 18.06.2023 17:14
void foo() { int dummy[3]; foo(dummy); }
Igor Tandetnik 18.06.2023 17:14

Может быть, передать std::array по указателю?

Jesper Juhl 18.06.2023 17:27

Повторно открыт, поскольку «дубликат» не отвечает, как использовать аргумент по умолчанию, в чем и заключается весь смысл этого вопроса.

eerorika 18.06.2023 17:42

Также рассмотрите void foo(const int (&arr)[3] = { 1, 2, 3 }), если вам не нужно изменять массив

Artyer 18.06.2023 21:31
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
6
89
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

В C++ нельзя напрямую передать значение по умолчанию массиву, переданному по ссылке. Однако вы можете добиться аналогичного эффекта, перегрузив функцию версией, которая принимает массив по умолчанию и вызывает с ним исходную функцию.

Вот код

void foo(int (&arr)[3]){}

void foo()
{
    int defaultArr[3] = {1, 2, 3};
    foo(defaultArr);
}
int main()
{
    int arr[3] = {2, 1, 4};
    foo(arr); 

    foo();     
    return 0;
}

Мне также нужно знать размер переданного массива, не передавая его размер, поэтому я этого не сделал: int (*arr)[3].

Это объяснение не имеет для меня смысла. Размер массива закодирован в типе указателя. Просто коснитесь указателя, и вы получите int (&arr) [3]. Пример:

void foo(int (*arr)[3] = nullptr)
{
    if (arr)
        std::cout << std::size(*arr);
    else
        std::cout << "nullptr";
}

Таким образом, использование указателя на массив является ответом на ваш вопрос.

Другой вариант — использовать необязательный диапазон:

void foo(std::optional<std::span<int, 3>> arr = std::nullopt)

Хотя тип параметра немного более подробный, он позволяет вам передавать массив напрямую, без использования оператора addressof. Кроме того, это позволяет передавать и другие непрерывные диапазоны, а не только массивы.


Если во время компиляции вы знаете, что вам нужна опция по умолчанию, я рекомендую использовать решение для перегрузки в ответе Сайеда, но это не сработает, если опция определена во время выполнения.

Эхх "Размер массива закодирован в типе указателя" - не совсем; вы не можете получить размер массива из указателя. Для этого вам понадобится std::array или std::vector - с участником .size() вы можете вызвать.

Jesper Juhl 18.06.2023 17:30

@JesperJuhl you cannot get the size of an array from a pointer. Да, вы можете получить размер из указателя на массив. You'd need a std::array or std::vector for that Нет, они вам не нужны.

eerorika 18.06.2023 17:32

пожалуйста, продемонстрируйте получение размера массива только из указателя на первый элемент массива. Докажи, что я неправ.

Jesper Juhl 18.06.2023 17:34

@JesperJuhl Я добавил пример.

eerorika 18.06.2023 17:35

@JesperJuhl from just a pointer to the first element of an array Ваша ошибка состоит в том, что вы думаете, что int (*arr)[3] — это указатель на первый элемент массива. Это не. Это указатель на весь массив.

eerorika 18.06.2023 18:01

@JeJo Верно, но тогда у нас есть шаблон, которого OP, возможно, следует избегать. Но если шаблон не проблема, то он действительно хорош для общности. Необязательная версия диапазона может быть создана аналогичным образом.

eerorika 18.06.2023 18:04

@JeJo std::optional might require the caller side also to change/ use/ convert the arrays to optional type as well Преобразование неявное и тривиальное.

eerorika 18.06.2023 18:10

@eerorika Хорошо, спасибо, извините, что не увидела правку.

Kesto2 18.06.2023 18:13

Другие вопросы по теме