Sie haben bereits einige Antworten für C und eine Antwort für C++ erhalten, aber es gibt eine andere Möglichkeit, dies in C++ zu tun.
Wie Nawaz sagte, eine Reihe von N Größe passieren, können Sie dies in C++ tun:
const size_t N = 16; // For your question.
void foo(int (&arr)[N]) {
// Do something with arr.
}
jedoch, wie von C++ 11, können Sie auch die std :: Array-Container, der mit einer natürlicheren Syntax übergeben werden kann (vorausgesetzt, die Template-Syntax ist vertraut).
#include <array>
const size_t N = 16;
void bar(std::array<int, N> arr) {
// Do something with arr.
}
Als Behälter, std :: Array ermöglicht meist die gleiche Funktionalität wie ein normaler C-Stil-Array, während auch eine zusätzliche Funktionalität hinzugefügt wird.
std::array<int, 5> arr1 = { 1, 2, 3, 4, 5 };
int arr2[5] = { 1, 2, 3, 4, 5 };
// Operator[]:
for (int i = 0; i < 5; i++) {
assert(arr1[i] == arr2[i]);
}
// Fill:
arr1.fill(0);
for (int i = 0; i < 5; i++) {
arr2[i] = 0;
}
// Check size:
size_t arr1Size = arr1.size();
size_t arr2Size = sizeof(arr2)/sizeof(arr2[0]);
// Foreach (C++11 syntax):
for (int &i : arr1) {
// Use i.
}
for (int &i : arr2) {
// Use i.
}
jedoch mein Wissen (die zugegebenermaßen zu der Zeit begrenzt ist), ist Pointer-Arithmetik nicht sicher mit std :: Array, wenn Sie die Member-Funktion Daten() verwenden, zuerst die tatsächlichen Arrays Adresse zu erhalten. Dies dient dazu, zu verhindern, dass zukünftige Änderungen an der Klasse std :: array Ihren Code unterbrechen, und weil manche STL-Implementierungen zusätzliche Daten zusätzlich zum eigentlichen Array speichern.
Beachten Sie, dass dies für neuen Code am nützlichsten sein würde, oder wenn Sie Ihren bereits vorhandenen Code umwandeln zu std :: Arrays anstelle von C-Stil-Arrays zu verwenden. Da es sich bei std :: arrays um Aggregattypen handelt, fehlen ihnen benutzerdefinierte Konstruktoren. Daher können Sie nicht direkt vom C-style-Array in std :: array wechseln (ohne einen Cast zu verwenden), aber das ist hässlich und kann in Zukunft Probleme verursachen).So wandeln sie, würden Sie stattdessen so etwas benötigen:
#include <array>
#include <algorithm>
const size_t N = 16;
std::array<int, N> cArrayConverter(int (&arr)[N]) {
std::array<int, N> ret;
std::copy(std::begin(arr), std::end(arr), std::begin(ret));
return ret;
}
Deshalb, wenn Ihr Code verwendet C-Stil-Arrays, und es wäre nicht durchführbar, es zu konvertieren std :: Arrays stattdessen zu verwenden, Sie würden besser mit C-artigen Arrays zu bleiben.
(Anmerkung: Ich Größen wie N angegeben, so dass Sie leichter den Code wiederverwenden können, wo immer Sie es brauchen.)
Edit: Es gibt ein paar Dinge, die ich vergessen zu erwähnen:
1) Die Mehrzahl der C++ - Standardbibliotheksfunktionen, die für den Einsatz auf Containern entwickelt wurden, sind implementationsunabhängig; Anstatt für bestimmte Container ausgelegt zu sein, operieren sie mit Iteratoren auf Reichweiten. (Das bedeutet auch, dass sie für std::basic_string
und instantiations arbeiten davon, wie std::string
.) Zum Beispiel std::copy
hat den folgenden Prototyp:
template <class InputIterator, class OutputIterator>
OutputIterator copy(InputIterator first, InputIterator last,
OutputIterator result);
// first is the beginning of the first range.
// last is the end of the first range.
// result is the beginning of the second range.
Während diese imposanten aussehen, Sie müssen in der Regel die Vorlage nicht angeben Parameter, und kann nur der Compiler das für Sie behandeln lassen.
std::array<int, 5> arr1 = { 1, 2, 3, 4, 5 };
std::array<int, 5> arr2 = { 6, 7, 8, 9, 0 };
std::string str1 = ".dlrow ,olleH";
std::string str2 = "Overwrite me!";
std::copy(arr1.begin(), arr1.end(), arr2.begin());
// arr2 now stores { 1, 2, 3, 4, 5 }.
std::copy(str1.begin(), str1.end(), str2.begin());
// str2 now stores ".dlrow ,olleH".
// Not really necessary for full string copying, due to std::string.operator=(), but possible nonetheless.
Wegen auf Iteratoren verlassen, sind diese Funktionen auch mit C-Stil-Arrays kompatibel (wie Iteratoren eine Verallgemeinerung von Zeigern, alle Zeiger sind definitionsgemäß Iteratoren sind (aber nicht alle Iteratoren sind notwendigerweise Zeiger)). Dies kann nützlich sein, wenn Sie mit Legacy-Code arbeiten, da Sie damit vollen Zugriff auf die Bereichsfunktionen in der Standardbibliothek haben.
int arr1[5] = { 4, 3, 2, 1, 0 };
std::array<int, 5> arr2;
std::copy(std::begin(arr1), std::end(arr1), std::begin(arr2));
Sie haben aus diesem Beispiel und die letzten bemerkt, dass std::array.begin()
und std::begin()
mit std::array
austauschbar verwendet werden. Dies liegt daran, dass std::begin()
und std::end()
so implementiert sind, dass sie für jeden Container den gleichen Rückgabetyp aufweisen und denselben Wert zurückgeben, wie beim Aufrufen der Elementfunktionen begin()
und end()
einer Instanz dieses Containers.
// Prototype:
template <class Container>
auto begin (Container& cont) -> decltype (cont.begin());
// Examples:
std::array<int, 5> arr;
std::vector<char> vec;
std::begin(arr) == arr.begin();
std::end(arr) == arr.end();
std::begin(vec) == vec.begin();
std::end(vec) == vec.end();
// And so on...
C-Stil-Arrays haben keine Elementfunktionen, was die Verwendung von std::begin()
und std::end()
für sie. In diesem Fall sind die zwei Funktionen überladen, um anwendbare Zeiger zu liefern, abhängig vom Typ des Arrays.
// Prototype:
template <class T, size_t N>
T* begin (T(&arr)[N]);
// Examples:
int arr[5];
std::begin(arr) == &arr[0];
std::end(arr) == &arr[4];
Als allgemeine Faustregel gilt, wenn Sie sich nicht sicher sind, ob nicht irgendein bestimmtes Codesegment wird im C-Stil-Arrays verwenden, ist es sicherer, std::begin()
und std::end()
zu verwenden.
[Beachten Sie, dass während der Verwendung von std::copy()
als Beispiel die Verwendung von Bereichen und Iteratoren in der Standardbibliothek sehr häufig ist. Die meisten, wenn nicht alle Funktionen, die für den Betrieb an Containern ausgelegt sind (oder genauer gesagt für alle Implementierungen der Container concept, wie-, std::vector
und std::string
), verwenden Bereiche, wodurch sie mit aktuellen und zukünftigen Containern sowie mit C kompatibel sind -artige Arrays. Es kann jedoch Ausnahmen von dieser weit verbreiteten Kompatibilität geben, die mir nicht bekannt sind.]
2) Wenn ein std :: -Array nach Wert übergeben wird, kann je nach Größe des Arrays ein beträchtlicher Overhead entstehen.Daher ist es normalerweise besser, sie als Referenz zu übergeben oder Iteratoren zu verwenden (wie die Standardbibliothek).
// Pass by reference.
const size_t N = 16;
void foo(std::array<int, N>& arr);
3) Alle diese Beispiele gehen davon aus, dass alle Arrays in Ihrem Code die gleiche Größe sein, wie durch die Konstante N
angegeben. Um Ihren Code mehr implementierungsunabhängig zu machen, können Sie entweder die Bereiche & Iteratoren selbst verwenden, oder wenn Sie Ihren Code auf Arrays fokussiert halten möchten, verwenden Sie Template-Funktionen. [Aufbauend auf this answer to another question.]
template<size_t SZ> void foo(std::array<int, SZ>& arr);
...
std::array<int, 5> arr1;
std::array<int, 10> arr2;
foo(arr1); // Calls foo<5>(arr1).
foo(arr2); // Calls foo<10>(arr2).
Wenn dies tun, können Sie sogar so weit gehen wie die Array-Mitglied Typ als auch als Templat, sofern der Code auf andere Typen als int arbeiten kann.
template<typename T, size_t SZ>
void foo(std::array<T, SZ>& arr);
...
std::array<int, 5> arr1;
std::array<float, 7> arr2;
foo(arr1); // Calls foo<int, 5>(arr1).
foo(arr2); // Calls foo<float, 7>(arr2).
Ein Beispiel hierfür finden Sie unter here.
Wenn jemand irgendwelche Fehler sieht, die ich vielleicht übersehen habe, können Sie sie auf mich hinweisen, um sie zu reparieren, oder sie selbst reparieren. Ich glaube, ich habe sie alle erwischt, aber ich bin mir nicht 100% sicher.
Würde es tatsächlich verhindern, dass der Benutzer ein Array [17] oder Array [15] erstellt? wenn ich denke, was genau int [] ist, ist es im Hintergrund ein int Zeiger auf ein nicht dynamisches Array. Würde das Programm/der Compiler automatisch eine andere Länge ablehnen, oder würde es es akzeptieren und versuchen, es so gut wie möglich zu handhaben? –
Das ist genau richtig, ich habe meine Antwort nach dem Test gelöscht. Ich dachte, ich könnte mit einer anderen Verwendung für Static (AUFS) knifflig werden und mit C99 'void foo gehen (int a [static 16]); aber ich habe gerade erkannt, dass garantiert * mindestens * 16 Mitglieder nicht * genau * wie gewünscht das OP – SiegeX
Also, wenn ich ein Array übergeben, das nicht der Größe 16 ist, wird es nicht kompilieren? Lass uns sagen, ich habe int intArray [20]; Sonderfall (& intArray). Wird das kompilieren? – armanali