2016-08-01 12 views
4

In C anzuwenden, ichein Fehler sicher neuer Betreiber für Zeiger auf Array

int (*ptr)[100]; 
ptr=malloc(sizeof *ptr); // this is the easy/error proof way of doing it 

Gibt es einen Fehler Beweis C++ Art und Weise das gleiche mit new Operator

int (*ptr)[100]; 
ptr=new __what_comes_here? 
+7

In C++ werden Sie wahrscheinlich tun 'std: : Vektor v (100); '. –

+2

Oder 'std :: array ' in diesem Fall. –

+5

Der elegante fehlerfreie Weg von C++ besteht darin, Arrays, Pointer oder 'new' zu vermeiden. –

Antwort

3
int (*ptr)[100]; 
tun

bedeutet ptr ist ein Zeiger, der eine Adresse eines Arrays von 100 ganzen Zahlen enthalten sollte. Mit anderen Worten, technisch, wenn Sie haben, so etwas wie:

int arr[100]; // automatic (compile time allocated) object of 100 integers 

Dann können Sie verwenden möchten:

ptr = &arr; 

Aber das ist hier nicht der Fall. So können Sie mit einem einfachen Zeiger machen. Wenn Sie dynamische gehen wollen dann entweder Sie malloc Äquivalent gehen:

int *p = new int[100]; // do `delete[] p` later to reclaim memory 

Beachten Sie, dass, p ist ein einfacher Zeiger, der die Adresse der ersten ganzen Zahl der dynamisch zugewiesenen Array enthält.

Aber besser ist es Standard-Container zu verwenden, jede Speicherverwaltung zu vermeiden:

std::vector<int> v(100); 

Wenn die Größe 100 festgelegt ist, dann können Sie verwenden:

int a[100]; // C-style 

Oder

std::array<int, 100> arr; // C++11 onwards 

Wenn Sie requi re new und haben keine Luxus über Einrichtungen verwenden wollen aber trotzdem die automatische Rückgewinnung von Speicher dann unique_ptr als following verwenden:

std::unique_ptr<int[]> p(new int[100]); 
+0

Er sucht, wie * die * Aufzählung in die' neue Aussage, aber folge aus der Zeigerdeklaration dem, was er mit malloc machen kann. – kfsone

+2

@kfsone, Sie werden ohne jegliche Haftung abgelehnt. Ein Zeiger auf Array ist NICHT erforderlich, um einen Speicher zu speichern, der von 'new/malloc' zugewiesen wurde. OP ist sich der Syntax in C++ wahrscheinlich nicht bewusst. 'int (* p) [N]' muss keinen dynamisch zugewiesenen Speicher enthalten. – iammilind

1

So wie ich bin hier zeigt offensichtlich keine gute Lösung, ich wollte nur Art, die Frage auf eine einzigartige Art und Weise zu beantworten.

template<typename> 
struct deref; 

template<typename T> 
struct deref<T*> 
{ 
    typedef T type; 
}; 

int main() { 
    int (*ptr)[100]; 
    ptr = new deref<decltype(ptr)>::type[1]; 
    return 0; 
} 

Ich weiß, dass die [1] offensichtlich höchst verdächtig ist, aber ohne es, das Ergebnis der new scheint nur Verfall zu einem int*. Also denke ich, dass das Addieren nur dazu führt, dass das "äußere" Array zerfällt und das Innere intakt bleibt.

Auch dies bedeutet, dass Sie delete[] aufrufen müssen, um es zu bereinigen und kein undefiniertes Verhalten zu verursachen.

Wenn Sie sich selbst davon überzeugen wollen, dass dies tatsächlich den benötigten Platz zuweist und es richtig zugreifen kann, sehen Sie the output of godbolt in an example.

+0

Das '[1]' bedeutet, dass Sie ein Einzelelement-Array von 'int [100]' s zuweisen, anstatt ein 100-Element-Array von 'int's. Sie erhalten also einen Zeiger auf das erste 'int [100]' Element in diesem neuen Array. Es sollte praktisch keine Bedeutung haben, da beide einen Block von 400 Bytes (für einen 32-Bit "int") und "delete []" müssen in der Lage sein, mit einem zu tun, auf den verwiesen wird durch seinen Parameter ohne Rücksicht auf den Typ erwarte ich. – TBBle

0
typedef int IntArray[100]; 

int main() 
{ 
    IntArray* p = new IntArray[1]; 

    delete[] p; 
    return 0; 
} 

Beachten Sie, dass Sie damit zugeordnete Array mit delete[] ausplanen müssen.

0

Nicht ganz, was Sie gefragt haben, aber Sie können, was Sie wollen mit Vorlagentyp Abzug.

template <typename T, std::size_t N> 
void populate_ptr(T (*&ptr)[N]) 
{ 
    // Its a shame the return value of new T[N] is T*, not T(*)[N] 
    ptr = reinterpret_cast<T(*)[N]>(new T[N]); 
} 

int (*ptr)[100]; 
populate_ptr(ptr); 
// Don't forget to delete[](ptr) later! 

Sie können keine Vorlagen auf Rückgabewerte ableiten, so dass Sie nicht Zuordnung verwenden, aber vorbei-by-reference sollte für alle Anwendungsfälle entsprechen.

Nicht, dass dies ein guter Weg ist der Umgang mit diesem, aber in der Lage Template-Typen Abzug gegen C-Stil-Arrays ist praktisch, von Zeit zu Zeit zu tun ..

+0

Während 'operator new []' 'void *' zurückgibt, ist der zurückgegebene Typ eines neuen Ausdrucks tatsächlich 'T *' – PeterT

+0

Sie können die Uminterpret-Umwandlung auch durch 'typedef T arrType [N]; ptr = new arrType [1]; 'das ist der gleiche" Trick ", den ich und Leon benutzt haben. – PeterT

+0

Danke @PeterT, ich habe den Kommentar über 'operator new []' 's Rückgabetyp korrigiert. Ich bin mir nicht sicher über den 'typedef' Trick, weil (Array ist Nick-picky) das Array ein Ein-Element-Array von 100 Element 'int' Arrays, anstatt ein 100-Elemente-Array von' int's zuweist. Ich kann mir nicht einfach einen praktischen Anwendungsfall vorstellen, um anders zu sein - eine Art "Operator-neue" Überladung, die Large-by-Count-Arrays vielleicht in einen anderen Pool umlenkt? Wie auch immer, meine Absicht war es, eine sichere Art der Verwendung von 'new T [N];' darzustellen, wobei T und N aus dem Typ des Zeigers extrahiert wurden. – TBBle