Передача массива в конструктор c

Обновлено: 24.04.2024

Исходный код примеров из этой статьи можете скачать из нашего github-репозитория.

Объявление массивов и инициализация массивов

Объявление массивов

Массив – это структура данных для хранения элементом определенного типа, имеющая фиксированный размер. Доступ к элементам массива производится по числовому индексу.

Для объявления массива, после указания типа его элементов, ставятся квадратные скобки:

Перед использованием, массив обязательно нужно проинициализировать, это можно сделать сразу, при его объявлении:

Либо после объявления:

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

Например, для указанного выше a3 – это будут нули, так как для типа int значение по умолчанию: 0;

Если попытаться вывести элементы массива na1 :

то приложение не будет собрано, т.к. массив предварительно нужно проинициализировать.

Инициализация массивов

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

После объявления массива значения элементам присваиваются через индекс:

Есть возможность задать конкретные значения в момент объявления с использованием ключевого слова new и указанием типа:

Либо без ключевого слова new:

Неявная типизация

При объявлении массива можно воспользоваться ключевым словом var . При этом тип элементов массива следует задать явно в правой части объявления:

Либо предоставить возможность “поработать” системе вывода типов:

Доступ к элементам массива. Обход элементов массива.

Как уже было сказано выше, за доступ к элементам массива отвечают числовые индексы:

При этом, если вы укажете индекс больше, чем максимально возможный, то будет выброшено исключение:

Приведенная выше строка приведет к выбросу следующего исключения:

Unhandled exception. System.IndexOutOfRangeException: Index was outside the bounds of the array .

Обход элементов массива можно производить с помощью циклов for , foreach и while , последний самый неудобный для работы с массивами, его мы рассматривать не будем. Если вы работаете с циклом for , то для указания верхней границы инкрементируемой переменной можно воспользоваться свойством Length у массива:

Более удобным для обхода элементов будет foreach :

Преимущество цикла for состоит в том, что в нем вы можете модифицировать элементы массива:

Передача массива в метод

Массивы являются ссылочным типом данных, это означает, что их значения хранятся в куче, а имя переменной массива является ссылкой на соответствующую область памяти. При передаче массива в качестве аргумента в метод, происходит присваивание значения переменной массива переменной определяющей аргумент, а так как имя массива – это ссылка, то фактически происходит передача ссылки на значение в куче. Поэтому, если вы передали массив в функцию и внутри этой функции произошла модификация этого массива, то исходный массив тоже изменится.

Создадим метода WorkWithArray , который изменяет содержимое массива:

Вызовем его в методе Main :

Ниже приведена иллюстрация того, как массив и ссылки на него располагаются в памяти.

Переменные na5 в методе Main и arr в методе WorkWithArray ссылаются на одну и ту же область памяти в куче, поэтому изменение массива через переменную arr отражается на переменной na5 .

Многомерные массивы

Прямоугольные массивы

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

Рассмотрим на примерах работу с такими массивами:

Зубчатые массивы

В зубчатых массивах элементами верхнего уровня являются другие массивы, это позволяет создавать многомерные структуры, у которых строки имеют разную длину:

Класс System.Array

Свойства класса System.Array

Имя свойства

Назначение

Число элементов в массиве. Учитываются все измерения.

Ранг массива – число измерений.

Методы класса System.Array

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

Имя метода

Назначение

BinarySearch(Array, Object)*

Выполняет поиск элемента в массиве.

Clear(Array, Int32, Int32)

Присваивает значение по умолчанию определенному количеству элементов массива начиная с заданного индекса.

Создает копию массива (неполную).

Copy(Array, Array, Int32)*

Копирует данные из одного массива в другой в заданном количестве.

CopyTo(Array, Int32)*

Копирует элементы из текущего массива в заданный, начиная с указанного индекса.

Exists(T[], Predicate)

Определяет наличие элемента удовлетворяющему предикату.

GetValue(Int32)*

Возвращает значение по указанному индексу.

IndexOf(Array, Object)*

Возвращает индекс первого вхождения элемента в массиве.

Reverse(Array)*

Задает обратный порядок для элементов в массиве.

Сортирует элементы массива.

Для вывода содержимого массива в консоль создадим метод PrintArray :

Ниже приведены примеры использования представленных выше методов и свойств класса System.Array :

Исходный код примеров из этой статьи можете скачать из нашего github-репозитория.

Здравствуйте!
Не получается передать двумерный массив как параметр конструктора.
Необходимо, чтобы пользователь ввел размерность квадратной матрицы и массив с клавиатуры. Эти значения надо передать конструктору с параметрами класса матрица.
Вот как я пытался это сделать:

Когда вывожу, то получается первый ряд правильно, а дальше нет.
Например если ввел матрицу
1 2 3
4 5 6
7 8 9
То в итоге получу:
1 2 3
-12323 -213230 -231213
-21312 -321321 -231231
Числа конечно не такие, но суть передал.
По заданию статическая матрица должна передаваться.
Подскажите, где я косячу?


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


Передача unique_ptr в конструктор другого класса
Как нужно передать unique_ptr в конструктор др. класса? есть такой код: .h файл: class.

Undefined reference или передача string в конструктор класса
Собственно проблема на этапе компиляции в main.cpp на 19 строке. Не понимаю, почему он требует 4.

Конструктор класса не видит конструктор по умолчанию другого класса
Ошибка, естественно, в Classes.cpp, в строке 20. Ругается, что у класса TailNode нет конструктора.

По-моему, матрица - указатель на указатели. Типа, ты делаешь указатель на указатели, а каждый из тех указателей указывает на блок в памяти, который выделен под определенную строчку. А у тебя

просто указатель на строчку, грубо говоря.

Добавлено через 1 минуту
То есть, если ты хочешь передать матрицу, то как-то так надо Matrix::Matrix(int xn, int** xA) , где xn - размер (а он нужен один, потому что у тебя квадратная матрица), а xA - указатель на указатели (а те указатели указывают на строчки).

Добавлено через 1 минуту
Хотя, я и сам могу ошибаться.

Добавлено через 7 минут
А, у тебя статическая матрица, тогда так:

В этой статье описывается использование массивов в C++/CLI.

Массивы с одним измерением

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

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

В этом примере показано, как выполнить агрегатную инициализацию для управляемого массива с несколькими измерениями:

Массивы массивов

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

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

Управляемые массивы как параметры типа шаблона

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

определения типов для управляемых массивов

В этом примере показано, как сделать typedef для управляемого массива:

Сортировка массивов

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

Для массивов, содержащих базовые встроенные типы, можно вызвать Sort метод. Можно переопределить критерий сортировки, и это необходимо сделать, если необходимо выполнить сортировку для массивов сложных типов. В этом случае тип элемента массива должен реализовывать CompareTo метод.

Сортировка массивов с помощью настраиваемых критериев

Для сортировки массивов, содержащих базовые встроенные типы, просто вызовите Array::Sort метод. Однако для сортировки массивов, содержащих сложные типы, или переопределения критериев сортировки по умолчанию Переопределите CompareTo метод.

В следующем примере структура с именем Element является производной от IComparable и написана для предоставления CompareTo метода, в котором в качестве критерия сортировки используется среднее арифметическое двух целых чисел.

Ковариация массивов

Данный ссылочный класс D с прямым или косвенным базовым классом B может быть присвоен массиву типа D переменной типа B.

Назначение элемента массива должно быть совместимо с присваиванием и динамическим типом массива. Присвоение значения элементу массива с несовместимым типом вызывает System::ArrayTypeMismatchException исключение.

Ковариация массивов не применяется к массивам типа класса значений. Например, массивы Int32 не могут быть преобразованы в массивы объектов ^, а не даже с помощью упаковки.

Массив — это последовательность объектов того же типа, которые занимают непрерывную область памяти. Традиционные массивы в стиле C являются источником многих ошибок, но по-прежнему являются распространенными, особенно в старых базах кода. В современном C++ настоятельно рекомендуется использовать std::vector или std::array вместо массивов в стиле C, описанных в этом разделе. Оба этих стандартных типа библиотек хранят свои элементы в виде непрерывного блока памяти. Однако они обеспечивают гораздо большую безопасность типов и поддерживают итераторы, которые гарантированно указывают на допустимое расположение в последовательности. Дополнительные сведения см. в разделе "Контейнеры".

Объявления стека

В объявлении массива C++ размер массива указывается после имени переменной, а не после имени типа, как в некоторых других языках. В следующем примере для стека объявляется массив из 1000 двойников. Число элементов должно быть предоставлено в виде целочисленного литерала или в виде константного выражения. Это связано с тем, что компилятору необходимо знать, сколько пространства стека необходимо выделить; Он не может использовать значение, вычисленное во время выполнения. Каждому элементу в массиве присваивается значение по умолчанию 0. Если вы не назначаете значение по умолчанию, каждый элемент изначально содержит любые случайные значения, которые будут находиться в этом расположении памяти.

Первый элемент в массиве является нулевым элементом. Последним элементом является элемент (n-1), где n — количество элементов, которые может содержать массив. Число элементов в объявлении должно быть целочисленным типом и должно быть больше 0. Ваша ответственность заключается в том, чтобы программа никогда не передает значение оператору подстрока, который больше (size - 1) .

Массив нулевого размера является допустимым только в том случае, если массив является последним полем в struct или union если расширения Майкрософт включены ( /Za или /permissive- не заданы).

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

Объявления кучи

Может потребоваться слишком большой массив для выделения в стеке или размер которого неизвестлен во время компиляции. Этот массив можно выделить в куче с помощью new[] выражения. Оператор возвращает указатель на первый элемент. Оператор подстрока работает с переменной указателя так же, как и в массиве на основе стека. Можно также использовать арифметические указатели для перемещения указателя на любые произвольные элементы в массиве. Вы несете ответственность за обеспечение следующего:

  • Всегда хранится копия исходного адреса указателя, чтобы можно было удалить память, если массив больше не нужен.
  • Адрес указателя не увеличивается или уменьшается после границ массива.

В следующем примере показано, как определить массив в куче во время выполнения. В нем показано, как получить доступ к элементам массива с помощью оператора подстрока и с помощью арифметики указателя:

Инициализация массивов

Массив можно инициализировать в цикле, по одному элементу за раз или в одной инструкции. Содержимое следующих двух массивов идентично:

Передача массивов в функции

Когда массив передается функции, он передается в качестве указателя на первый элемент, будь то массив на основе стека или кучи. Указатель не содержит дополнительных сведений о размере или типе. Такое поведение называется разложением указателя. При передаче массива в функцию необходимо всегда указывать количество элементов в отдельном параметре. Это также означает, что элементы массива не копируются при передаче массива в функцию. Чтобы предотвратить изменение элементов функцией, укажите параметр в качестве указателя на const элементы.

В следующем примере показана функция, которая принимает массив и длину. Указатель указывает на исходный массив, а не копию. Так как параметр не const задан, функция может изменять элементы массива.

Объявите и определите параметр p массива так, const чтобы он был доступен только для чтения в блоке функции:

Эту же функцию также можно объявить таким образом, без каких-то изменений в поведении. Массив по-прежнему передается в качестве указателя на первый элемент:

Многомерные массивы

Массивы, созданные из других массивов, являются многомерными. Такие многомерные массивы определяются путем последовательного размещения нескольких константных выражений, заключенных в квадратные скобки. Рассмотрим, например, следующее объявление:

Он задает массив типа int , концептуально упорядоченный в двумерной матрице из пяти строк и семи столбцов, как показано на следующем рисунке:


Концептуальная структура многомерного массива

Можно объявить многомерные массивы с списком инициализаторов (как описано в инициализаторах). В этих объявлениях можно опустить константное выражение, указывающее границы для первого измерения. Пример:

В показанном выше объявлении определяется массив, состоящий из трех строк и четырех столбцов. Строки представляют фабрики, а столбцы — рынки, на которые фабрики поставляют свою продукцию. Значения — это стоимости транспортировки с фабрик на рынки. Первое измерение массива опущено, но компилятор заполняет его, проверяя инициализатор.

Использование оператора косвенного обращения (*) в типе n-мерного массива приводит к получению массива n-1. Если n равно 1, создается скаляр (или элемент массива).

Массивы C++ размещаются в памяти по срокам. Построчный порядок означает, что быстрее всего изменяется последний индекс.

Пример

Можно также опустить спецификацию границ для первого измерения многомерного массива в объявлениях функций, как показано ниже:

Эта функция FindMinToMkt записывается таким образом, что добавление новых фабрик не требует каких-либо изменений в коде, а просто перекомпиляции.

Инициализация массивов

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

Рассмотрим класс Point , определяющий два конструктора:

Первый элемент aPoint создается с помощью конструктора Point( int, int ) , а оставшиеся два элемента — с помощью конструктора по умолчанию.

Статические массивы элементов (независимо от того, можно ли const ) инициализировать в их определениях (за пределами объявления класса). Пример:

Доступ к элементам массива

К отдельным элементам массива можно обращаться при помощи оператора индекса массива ( [ ] ). Если вы используете имя одномерного массива без подстрока, оно вычисляется как указатель на первый элемент массива.

Если используются многомерные массивы, в выражениях можно использовать различные сочетания.

В приведенном выше коде multi представляет собой трехмерный массив типа double . Указатель p2multi указывает на массив типа double размера 3. В этом примере массив используется с одним, двумя и тремя индексами. Хотя обычно указываются все подстроки, как в инструкции cout , иногда бывает полезно выбрать определенное подмножество элементов массива, как показано в следующих cout инструкциях.

Перегруженный оператор подстрочного индекса

Как и другие операторы, оператор подстрока ( [] ) может быть переопределен пользователем. Поведение оператора индекса по умолчанию, если он не перегружен, — совмещать имя массива и индекс с помощью следующего метода.

Как и во всех дополнениях, включающих типы указателей, масштабирование выполняется автоматически для настройки размера типа. Результирующая величина не является n байтами из источника array_name ; вместо этого это n-й элемент массива. Дополнительные сведения об этом преобразовании см. в разделе "Аддитивные операторы".

Аналогично, для многомерных массивов адрес извлекается с использованием следующего метода.

((array_name) + (subscript1 * max2 * max3 * . * maxn) + (subscript2 * max3 * . * maxn) + . + subscriptn))

Массивы в выражениях

Если идентификатор типа массива отображается в выражении, отличном от sizeof адреса ( & ) или инициализации ссылки, он преобразуется в указатель на первый элемент массива. Пример:

Указатель psz указывает на первый элемент массива szError1 . Массивы, в отличие от указателей, не являются изменяемыми l-значениями. Вот почему следующее назначение является незаконным:

Я хотел бы модернизировать небольшую математическую библиотеку, используя новые парадигмы C ++ (у меня есть компилятор C ++ 17). В частности, мне нужно передать массив в класс через конструктор.

Это «классический» старый способ, которым я пользовался. Оно работает

Итак, я попытался изменить класс Vector с помощью того, что я понял о шаблонах с переменными параметрами и пакете параметров. Не работает

Ошибка, возвращаемая компилятором

ошибка: невозможно преобразовать long long * в long double при инициализации

Что я делаю неправильно? Кроме того, мне интересно, возможно ли использовать std :: array вместо raw array как внутри основного метода, так и в классе Vector.

3 ответа

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

Вы можете определить свой собственный вектор и при этом использовать преимущества std :: vector для создания ваших векторных объектов. Например с наследованием:

В случае композиции вам нужно определить нужные вам конструкторы.

В обоих случаях вы можете использовать свой собственный вектор следующим образом:

Как вы видите с std :: vector, вы получаете все преимущества, необходимые для создания вашего собственного объекта Vector.

Передача такого массива не является решением. Шаблоны Variadic используются для передачи N номеров параметров в класс / функцию. И все же вы передаете только один параметр!

Я бы посоветовал вам

Я предлагаю вам использовать ссылки на массивы, которые доступны во всех версиях C ++:

Кстати, если вы можете, используйте вектор. Я очень сомневаюсь, что этот пользовательский векторный класс так же эффективен, как std::vector (без геометрического роста или оптимизированного копирования и перемещения)

Согласно вашему определению

Вы хотите использовать этот конструктор следующим образом:

Это возможно, если вы слегка измените свое определение конструктора так:

Обратите внимание, что такой вид использования не является хорошей практикой, обычно вы должны использовать std контейнеры и избегать использования new .

Читайте также: