Оскільки існує std::list
і std::vector
існує, чи є причина використовувати традиційні масиви C в C ++, або їх слід уникати, як malloc
?
Оскільки існує std::list
і std::vector
існує, чи є причина використовувати традиційні масиви C в C ++, або їх слід уникати, як malloc
?
Відповіді:
У C ++ 11, де std::array
це можливо, відповідь: "так, слід уникати масивів". До C ++ 11 вам може знадобитися використовувати масиви C, щоб розподілити масиви в автоматичному сховищі (тобто в стеку).
Безумовно, хоча і std::array
в C ++ 11, практично лише для статичних даних. Масиви в стилі С мають три важливі переваги перед
std::vector
:
Вони не потребують динамічного розподілу. З цієї причини слід віддавати перевагу масивам стилю C там, де у вас, ймовірно, буде багато дуже маленьких масивів. Скажіть щось на зразок точки n-виміру:
template <typename T, int dims>
class Point
{
T myData[dims];
// ...
};
Як правило, можна уявити, що dims
він буде дуже маленьким (2 або 3),
T
вбудованим типом ( double
), і що у вас може вийти
std::vector<Point>
мільйони елементів. Ви точно не хочете мільйонів динамічних розподілів з 3 подвійних.
Підтримка статичної ініціалізації. Це проблема лише для статичних даних, де щось на зразок:
struct Data { int i; char const* s; };
Data const ourData[] =
{
{ 1, "one" },
{ 2, "two" },
// ...
};
Це часто переважніше використання вектора (і std::string
), оскільки це дозволяє уникнути усіх питань порядку ініціалізації; дані попередньо завантажуються, перш ніж будь-який фактичний код може бути виконаний.
Нарешті, що стосується вищесказаного, компілятор може обчислити фактичний розмір масиву за ініціалізаторами. Не потрібно їх рахувати.
Якщо у вас є доступ до C ++ 11, std::array
вирішує перші дві проблеми, і, безумовно, слід використовувати перевагу масивів стилю C у першому випадку. Однак це не стосується третього, і наявність розміру компілятора масиву відповідно до кількості ініціалізаторів все ще є вагомою причиною віддавати перевагу масивам стилю C.
int i[] = { 1, 2, 3 };
продовжує працювати з int i[] = { 1, 2, 3, 4 };
. array<int, 3>
потрібно вручну змінити на array<int, 4>
.
make_array
функцію , подібну до make_pair
ін. Капелюшок до @R. Мартіньо Фернандес .
std::array
в C ++ 11, [їх слід використовувати] практично лише для статичних даних".
Ніколи не кажіть "ніколи", але я б погодився, що їх роль значно зменшується завдяки справжнім структурам даних від STL.
Я б також сказав, що інкапсуляція всередині об’єктів повинна звести до мінімуму вплив такого вибору. Якщо масив є приватним членом даних, ви можете поміняти його місцями або змінити, не впливаючи на клієнтів вашого класу.
Я працював над критичними системами безпеки, де ви не можете використовувати динамічне розподіл пам'яті. Пам'ять завжди повинна бути в стеку. Тому в цьому випадку ви використовуєте масиви, оскільки розмір фіксується під час компіляції.
std::array<T>
розподіляє по стеках і в основному не має накладних витрат на необроблений масив.
array
in c++
дає вам швидкий варіант фіксованого розміру динамічного розміру std::vector
та std::list
. std :: array - одне з доповнень у c++11
. Це забезпечує переваги контейнерів std, одночасно забезпечуючи сукупну семантику типів масивів у стилі C.
Тому c++11
я б, звичайно, використовував std::array
, де це потрібно, над вектором. Але я б уникнути масив стилів C в C++03
.
Більшість зазвичай, немає , я не можу думати про причини використання сировинних масивів над, скажімо, vectors
. Якщо код новий .
Можливо, вам доведеться вдатися до використання масивів, якщо ваші бібліотеки повинні бути сумісними з кодом, який очікує на масиви та необроблені вказівники.
vector.data()
у C ++ 11 або &vector.front()
раніше.
Я знаю, що багато людей вказують на std :: array для розподілу масивів у стеку та std :: vector для купи. Але, схоже, жодна з них не підтримує неприродне вирівнювання. Якщо ви робите будь-який числовий код, для якого ви хочете використовувати інструкції SSE або VPX (таким чином, вимагаючи вирівнювання 128 або 256 байт відповідно), масиви C все ще здаються вашим найкращим вибором.
Я б сказав, що масиви все ще корисні, якщо ви зберігаєте невеликий статичний обсяг даних, чому б і ні.
Єдина перевага масиву (звичайно, загорнутого в щось, що автоматично управлятиме його вивільненням у разі потреби) над тим, про що std::vector
я можу подумати, це те, що він vector
не може передавати право власності на свої дані, якщо ваш компілятор не підтримує C ++ 11 та не переміщує конструктори.
swap
.
Масиви стилю С є фундаментальною структурою даних, тому траплятимуться випадки, коли краще використовувати її. Однак для загального випадку використовуйте вдосконаленіші структури даних, які заокруглюють кути базових даних. C ++ дозволяє робити дуже цікаві та корисні речі з пам'яттю, багато з яких працюють із простими масивами.
std::array
s? У багатьох випадках обидва вони складатимуться до однієї і тієї ж збірки.
std::array
має точно визначену семантику, побудовану поверх статичних масивів.
Ви повинні використовувати контейнери STL всередині, але ви не повинні передавати покажчики на такі контейнери між різними модулями, інакше ви потрапите в пекло залежностей. Приклад:
std::string foo;
// fill foo with stuff
myExternalOutputProc(foo.c_str());
це дуже хороше рішення, але ні
std::string foo;
// fill foo with stuff
myExternalOutputProc(&foo);
Причина в тому, що std :: string може бути реалізований різними способами, але рядок у стилі c - це завжди рядок у стилі c.