array bound forbidden after parenthesized type-id

Le
Lucas Levrel
Bonjour,

J'utilise des objets alloués dynamiquement comme suit :
double (*data)[3];
data=new double[t][3];

Maintenant, je voudrais en faire un tableau. J'essaye donc :

double (**tab)[3];
tab=new (double(*)[3])[n];
for(int i=0;i<n;i++) tab[i]=new double[t][3];

et le compilateur (g++) me donne l'erreur que j'ai mise en sujet.
Est-ce que le code suivant, qui compile sans erreur, est équivalent à ce
que je veux faire ?

typedef double(*data_type)[3];
data_type *tab;
tab=new data_type[n];
for

Si oui, pourquoi le compilateur refuse-t-il le premier code et pas le
second ?

Merci d'avance.
--
LL
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses Page 1 / 6
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
Fabien LE LEZ
Le #19802161
On Tue, 21 Jul 2009 17:49:29 +0200, Lucas Levrel

J'utilise des objets alloués dynamiquement comme suit :
double (*data)[3];
data=new double[t][3];



Tu as une raison de vouloir faire ça, ou tu aimes juste les ennuis ?

Le type "tableau" en C++, c'est std::vector<>. On peut décider
d'utiliser autre chose, mais seulement après y avoir mûrement
réfléchi.
James Kanze
Le #19803411
On Jul 21, 5:49 pm, Lucas Levrel
J'utilise des objets alloués dynamiquement comme suit :
double (*data)[3];
data=new double[t][3];



Maintenant, je voudrais en faire un tableau. J'essaye donc :



double (**tab)[3];
tab=new (double(*)[3])[n];
for(int i=0;i<n;i++) tab[i]=new double[t][3];



Pourquoi faire simple quand on peut faire compliquer, n'est
pas ? Comme dit Fabien, std::vector est ton ami.

Quant à l'erreur, il aurait été plus simple si tu avais indiqué
quelle ligne provoquait l'erreur, mais à jouer aux devinettes
(« but just a guess », an anglais -- je ne trouve rien de mieux
en français, à cette heure du soir) : la première expression new
me semble louche. La syntaxe de new ne permet que deux
variants (sans les placement et d'autres) :
new new-type-id
new ( type-id )
Or, new-type-id ne permet qu'une expression assez limitée des
types, sans parenthèses. C-à-d que ta ligne se parse :

tab = (new (double (*)[3])) [n] ;

Le [n] n'apppartient pas à l'expression new. Et bien que l'expression
à
droite de l'affectation est tout à fait légale, le type qu'il en
donne (le résultat d'avoir appliqué l'operateurr [] sur le
résultat de l'expression new) n'est pas compatible avec le type
à gauche de l'affectation.

Si tu y tiens,
tab=new (double((*[n])[3])) ;
doit faire l'affaire. Mais je n'aimerais pas !a avoir à
maintenir de tel code.

et le compilateur (g++) me donne l'erreur que j'ai mise en
sujet. Est-ce que le code suivant, qui compile sans erreur,
est équivalent à ce que je veux faire ?



typedef double(*data_type)[3];
data_type *tab;
tab=new data_type[n];
for...



L'effet est sans doute le même. Et c'est plus lisible aussi.
Mais encore loin de ce qu'on aurait avec std::vector.

Si oui, pourquoi le compilateur refuse-t-il le premier code et
pas le second ?



Parce que le permier n'est pas légal, et le second si.

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
pjb
Le #19805411
Fabien LE LEZ
On Tue, 21 Jul 2009 17:49:29 +0200, Lucas Levrel

J'utilise des objets alloués dynamiquement comme suit :
double (*data)[3];
data=new double[t][3];



Tu as une raison de vouloir faire ça, ou tu aimes juste les ennuis ?

Le type "tableau" en C++, c'est std::vector<>. On peut décider
d'utiliser autre chose, mais seulement après y avoir mûrement
réfléchi.



En fait, ici j'ai l'impression que Lucas veut non pas des vecteurs,
mais des tableaux multidimentionnel, ou peut être seulement des
matrices.



class InvalidRow : public std::exception { ... };
class InvalidColumn : public std::exception { ... };

template <class Element> Column {
Matrix<Element>& matrix;
size_t column;
public:
Column(Matrix<Element>& aMatrix,size_t aColumn)
:matrix(aMatrix),column(aColumn) {};
Element& operator[](size_t row){ return(matrix.at(column,row)); }
};

template <class Element> Matrix {
size_t width;
size_t height;
Element* data;
public:
Matrix(size_t aWidth,size_t aHeight)
:width(aWidth),height(aHeight) {
data=new Element[aWidth*aHeight];
}
virtual ~Matrix(){ delete data; };
Column<Element>& operator[](size_t column){
if((0<=column) and (column<width)){
return(Column<Element>(*this,column);
}else{
throw InvalidColumn(column,width);
}
};
Element& at(size_t column,size_t row){
if((0<=column) and (column<width)){
if((0<=row) and (row<height)){
return(this->data[column*width+row]);
}else{
throw InvalidRow(row,height);
}
}else{
throw InvalidColumn(column,width);
}
};
Matrix<Element>& operator=(Matrix<Element>& other) const { ... };
bool operator==(Matrix<Element>& other){ ... };
Matrix<Element>& operator+(Matrix<Element>& other){ ... };
Matrix<Element>& operator-(Matrix<Element>& other){ ... };
Matrix<Element>& operator*(Matrix<Element>& other){ ... };
Matrix<Element>& operator*(const Element& scalar){ ... };
...
};

--
__Pascal Bourguignon__
Fabien LE LEZ
Le #19805941
On Wed, 22 Jul 2009 10:47:13 +0200, (Pascal J.
Bourguignon):

En fait, ici j'ai l'impression que Lucas veut non pas des vecteurs,



Possible. Je n'ai jamais parlé de vecteurs.

mais des tableaux multidimentionnel, ou peut être seulement des
matrices.



Un tableau de T à une dimension s'écrit vector<T>.
Un tableau de T à deux dimensions s'écrit vector< vector<T> >.
Un tableau de T à trois dimensions s'écrit
vector< vector< vector<T> > >.
etc.

Une matrice au sens mathématique est généralement une encapsulation
d'un vector< vector<T> >.
Lucas Levrel
Le #19806301
Le 21 juillet 2009, James Kanze a écrit :

Quant à l'erreur, il aurait été plus simple si tu avais indiqué
quelle ligne provoquait l'erreur,



Ah oui, désolé ! C'est cette ligne qui coince :
tab=new (double(*)[3])[n];

C-à-d que ta ligne se parse :

tab = (new (double (*)[3])) [n] ;

Le [n] n'apppartient pas à l'expression new.



OK. Pour me fixer les idées, quand on fait :
toto = new double[n];
c'est bien parsé comme new (double[n]) et non pas (new double)[n] ?

Si tu y tiens,
tab=new (double((*[n])[3])) ;
doit faire l'affaire. Mais je n'aimerais pas !a avoir à
maintenir de tel code.



Effectivement. Ça crée bien un tableau de n objets de type double(*)[3] ?

Merci pour tes explications.
--
LL
Lucas Levrel
Le #19806431
Merci pour votre aide !

En fait je veux un tableau à 3 dimensions n*t*3, et comme n et t sont très
grands, je ne veux pas qu'il occupe beaucoup plus que n*t*3*64 bits. Sinon
j'aurais fait :
double ***tab;
tab=new (double **)[n];
for(int i=0;i<n;i++){
tab[i]=new (double *)[t];
for(int j=0;j<t;j++) tab[i][j]=new double[3];
}
mais (sauf erreur dans mes tests) new double[3] consomme 4*64 bits.

De plus, ça m'arrange que les doubles soient contigus par paquets de t*3,
pour faire une écriture non formatée comme :
file_out.write((char*)tab[i],t*3*sizeof(double));

Tout ça m'a conduit à l'idée de faire des new double[t][3] et un tableau
de n pointeurs vers ceux-ci.

Mais, si ça existe, je suis preneur d'une façon de faire plus lisible et
pas significativement plus gourmande en mémoire. Comme l'a deviné Pascal,
les dimensions n et t sont constantes.

--
LL
Fabien LE LEZ
Le #19806811
On Wed, 22 Jul 2009 13:17:10 +0200, Lucas Levrel :

En fait je veux un tableau à 3 dimensions n*t*3, et comme n et t sont très
grands, je ne veux pas qu'il occupe beaucoup plus que n*t*3*64 bits



std::vector<> répond à la demande. Il suffit de l'encapsuler dans une
classe qui va bien :


template <class T> class TableauTailleFixe3D
{
public:
TableauTailleFixe3D (size_t taille1_,
size_t taille2_, size_t taille3_)
: taille2 (taille2_)
, taille3 (taille3_)
, data (taille1_ * taille2_ * taille3_)
{}

T& operator() (size_t pos1, size_t pos2, size_t pos3)
{
return data [Index (pos1, pos2, pos3)];
}

T const& operator() (size_t pos1, size_t pos2, size_t pos3) const
{
return data [Index (pos1, pos2, pos3)];
}

private:
size_t Index (size_t pos1, size_t pos2, size_t pos3) const
{ return (pos1 * taille2 + pos2) * taille3 + pos3; }

size_t taille2, taille3;
std::vector<T> data;
};



Initialisation :

typedef TableauTailleFixe3D <long long> Tableau;
Tableau tab (n, t, 3);

Pour modifier la case (17,36,2) :

tab (17, 36, 2)= 42;
Fabien LE LEZ
Le #19806801
>typedef TableauTailleFixe3D <long long> Tableau;



Remplacer "long long" par "double" dans ton cas.
pjb
Le #19806981
Fabien LE LEZ
On Wed, 22 Jul 2009 10:47:13 +0200, (Pascal J.
Bourguignon):

En fait, ici j'ai l'impression que Lucas veut non pas des vecteurs,



Possible. Je n'ai jamais parlé de vecteurs.



Mais tu as parlé de std::vector, ce qui en français se dit "vecteur".


mais des tableaux multidimentionnel, ou peut être seulement des
matrices.



Un tableau de T à une dimension s'écrit vector<T>.
Un tableau de T à deux dimensions s'écrit vector< vector<T> >.
Un tableau de T à trois dimensions s'écrit
vector< vector< vector<T> > >.



Non.


--
__Pascal Bourguignon__
pjb
Le #19806971
Fabien LE LEZ
On Wed, 22 Jul 2009 13:17:10 +0200, Lucas Levrel :

En fait je veux un tableau à 3 dimensions n*t*3, et comme n et t sont très
grands, je ne veux pas qu'il occupe beaucoup plus que n*t*3*64 bits



std::vector<> répond à la demande. Il suffit de l'encapsuler dans une
classe qui va bien :



Faire des vecteurs de vecteurs pose des gros problèmes de gestion de
mémoire et de temps d'accès aux éléments.

Mieux vaut faire comme le je démontrais, et comme le font tous les
compilateurs de tous les autres languages qui eux supportent les
tableaux multidimensionnels, (ce n'est pas "rocket-science" pourtant),
une seule allocation, et un indexage direct.


--
__Pascal Bourguignon__
Publicité
Poster une réponse
Anonyme