7

Ich bin ziemlich neu in C++ mit Boost.Zeiger auf eine Klasse in dynamisch zugewiesenen Boost multi_array, nicht kompilieren

Ich möchte ein Objekt der Klasse "Welt" ein Array namens "Chunk" vom Typ "octreenode" haben. Zuvor hatte ich ein gewöhnliches eindimensionales Array, und das funktionierte gut. Jetzt versuche ich, ein 3D-Array mit Boosts multi_array-Funktionalität zu verwenden, und ich bin mir wirklich nicht sicher, was ich falsch mache.

Vereinfachte Code:

class world { 
public: 

    typedef boost::multi_array<octreenode, 3> planetchunkarray; // a boost_multi for chunks 
    typedef planetchunkarray::index index; 
    planetchunkarray *chunk; 

    world(double x,double y,double z, 
     int widtheast, int widthnorth, int height) : 
     originx(x), originy(y), originz(z), 
     chunkseast(widtheast), chunksnorth(widthnorth), chunksup(height) { 

    chunk = new planetchunkarray(boost::extents[chunksnorth][chunkseast][chunksup]); 
    planetchunkarray::extent_gen extents; 

    for (int cz = 0; cz < chunksnorth; ++cz) { 
     for (int cx = 0; cx < chunkseast; ++cx) { 
     for (int cy = 0; cy < chunksup; ++cy) { 
      (*chunk)[cz][cx][cy] = new octreenode(1,72); 
     } 
     } 
    } 
    } 
}; 

Nach dem, wenn ich den Auftrag

root->planet[0]->chunk[0][0][0]->material = 4;

ich den Fehler zu machen versuchen:

error: base operand of '->' has non-pointer type 'boost::detail::multi_array::sub_array<octreenode, 1u>'| 

"octreenode" hat den entsprechenden Konstruktor, und diese Zeile funktionierte in identischer Syntax, als es gerade war:

root->planet[0]->chunk[0]->material = 4;

(mit einem eindimensionalen Array). In ähnlicher Weise, während sie mit einem eindimensionalen Array fein kompilierten und versuchen, die Chunk-Funktionen zu übergeben, einen Zeiger auf ein „octreenode“ Objekt erwarten, wie zum Beispiel:

compactoctree(root->planet[p]->chunk[cz][cx][cy], 0, 14);

erzeugt die Fehler

error: cannot convert 'boost::detail::multi_array::sub_array<octreenode, 1u>' to 'octreenode*' for argument '1' to 'short int compactoctree(octreenode*, int, int)'| 

Wäre sehr dankbar für irgendwelche Vorschläge, ich bin sicher, ich vermisse etwas offensichtlich.

+0

(der Vorschlag von dereferencing "Brocken", die speziell von https kam zu konstruieren: // Gruppen .google.com/forum /? fromgroups = #! topic/boost-list/IWKIdlrg4dU) – Riot

Antwort

4

Ihr Array ist der Werttyp (octreenode), aber kein Zeigertyp (octreenode*)

Deshalb sind Sie eigentlich nicht versuchen, einen Zeiger auf einen dynamisch zugewiesenen octreenode zuweisen (new ist für Heapzuordnung standardmäßig aktiviert) .

Weisen Sie stattdessen nur einen Wert:

 (*chunk)[cz][cx][cy] = octreenode(1,72); 

In der Tat gibt es keinen Grund, new auf dem Multi-Array in erster Linie entweder zu verwenden:

UPDATE

In den Kommentaren es wurde angesprochen, dass mehr Dinge optimiert werden könnten und dass Sie diese nützlichen Ergänzungen zu der Antwort auf den Kompilierungsfehler betrachten.

So, hier geht: Wenn Sie in der Tat alle Array-Elemente mit dem exakt gleichen Wert initialisiert werden soll,

  1. Sie können die Schleifen Art und Weise effizienter machen, indem für einen Moment über die Array-Formen zu vergessen:

    std::fill_n(chunk.data(), chunk.num_elements(), octreenode {1, 72}); 
    

    Wenn Sie octreenode wissen, ist ein POD-Typ, Sie konnte schreiben

    std::uninitialzed_fill_n(chunk.data(), chunk.num_elements(), octreenode {1, 72}); 
    

    aber eine intelligente Bibliothek Implementierung würde am Ende fill_n sowieso aufrufen (weil es keinen Gewinn gibt). Sie können uninitialized_fill_n, wenn octreenode ist nicht ein POD-Typ, aber es ist trivial zerstörbar.

  2. In der Tat gibt es keinen Grund, auf dem Multi-Array in erster Linie neu zu verwenden. Sie können nur den Konstruktor Initialisierungsliste verwenden, um das multi_array Mitglied


Live On Coliru

#include <boost/multi_array.hpp> 
#include <type_traits> 

struct octreenode { int a; int b; }; 

class world { 
public: 
    world(double x, double y, double z, int widtheast, int widthnorth, int height) 
      : 
       originx(x), originy(y), originz(z), 
       chunkseast(widtheast), chunksnorth(widthnorth), chunksup(height), 
       chunk(boost::extents[chunksnorth][chunkseast][chunksup]) 
    { 
     octreenode v = { 1, 72 }; 
     std::fill_n(chunk.data(), chunk.num_elements(), v); 
    } 

private: 
    double originx, originy, originz; 
    int chunkseast, chunksnorth, chunksup; 

    typedef boost::multi_array<octreenode, 3> planetchunkarray; // a boost_multi for chunks 
    typedef planetchunkarray::index index; 
    planetchunkarray chunk; 
}; 

int main() { 
    world w(1,2,3,4,5,6); 
} 
+0

Da ich das vor ein paar Jahren gefragt habe, ist es etwas schwierig, sich den Kontext zu merken, aber das Multi-Array wird deklariert rot auf dem Haufen, weil es für den Stapel zu groß war; Der Wunsch, die Chunks gleichzeitig im Speicher zu haben, war die Absicht dahinter, das Multi-Array von Nicht-Pointern auf dem Heap zuzuordnen und nicht ein Array von Zeigern, die überall sein konnten und den Cache während der Dereferenzierung und Iteration durchkreuzten. Allerdings kann ich jetzt zurückblicken, dass mein Versuch, auf diese Weise "neuen octrenode" zu verwenden, fehl am Platz war, und ich hätte die Platzierungsform von new verwenden sollen. Ich werde eine Antwort posten. – Riot

+0

Mmm. Ich denke, das lehrt mich, mich von der "unbeantworteten" Warteschlange fernzuhalten ... – sehe

+2

ich hoffe nicht! Ihre Antwort hat mich dazu veranlasst, dies noch einmal zu wiederholen, und hoffentlich wird diese Diskussion für jemanden von Nutzen sein, der in Zukunft von Google kommt. – Riot

Verwandte Themen