Les différences de l'utilisation de “const cv::Mat &”, “cv::Mat &”, “cv::Mat” ou “const cv::Mat” comme les paramètres de la fonction?
J'ai cherché à fond et n'ont pas trouvé une réponse simple à cette.
Passant opencv matrices (cv::Mat
) que les arguments d'une fonction, nous sommes le passage d'un pointeur intelligent. Tout changement que nous faisons à l'entrée de la matrice à l'intérieur de la fonction modifie la matrice à l'extérieur de la portée de la fonction en tant que bien.
J'ai lu que par le passage d'une matrice comme const de référence, il n'est pas modifié à l'intérieur de la fonction. Mais un simple exemple montre qu'il n':
void sillyFunc(const cv::Mat& Input, cv::Mat& Output){
Output = Input;
Output += 1;
}
int main( int argc, char** argv ){
cv::Mat A = cv::Mat::ones(3,3,CV_8U);
std::cout<<"A = \n"<<A<<"\n\n";
cv::Mat B;
sillyFunc(A,B);
std::cout<<"A = \n"<<A<<"\n\n";
std::cout<<"B = \n"<<B<<"\n\n";
}
Clairement, A
est altérée, même si il est envoyé comme un const cv::Mat&
.
Cela ne m'étonne pas qu'au sein de la fonction I2
est une simple copie de I1
's pointeur intelligent et ainsi tout changement dans I2
va modifier I1
.
Ce n'déflecteur moi, c'est que je ne comprends pas quelle différence existe entre l'envoi de cv::Mat
, const cv::Mat
, const cv::Mat&
ou cv::Mat&
que les arguments d'une fonction.
Je sais comment faire pour remplacer ce (en remplacement de Output = Input;
avec Output = Input.clone();
permettrait de résoudre le problème), mais ne comprends toujours pas le ci-dessus mentionné différence.
Merci les gars!
- nice pathologique des exemples 😉
- pas sûr à 100% mais je pense que
cv::Mat
est une "tête" de la classe qui détient certains des octets de l'information, afincv::Mat &
comme paramètre n'a pas besoin pour copier l'en-tête. Const vs non-const peut montrer à l'utilisateur que les éléments de la matrice ne sont PAS DESTINÉS à être modifié lors de l'appel de la fonction, tandis que la lecture de l'en-tête/documentation. - Si vous pensez que le
Mat
's que les en-têtes autour de quelques données, vous pouvez voir comment vous pouvez copier l'en-tête et ainsi de modifier les données via une autre voie, mais vous ne pouvez pas modifier la "tête" même si vous avez passé commeconst
. Par exemple, vous ne pouvez pas modifier le nombre de lignes, de colonnes ou de type deInput
et si vous essayez de le faire viaOutput
, il compile mais ne changerait pasInput
, il serait juste de réaffecterOutput
à de nouvelles données. - Si votre fonction avait été
void sillyFunc(const cv::Mat* Input, cv::Mat* Output)
, le compilateur ne pas vous laisser jeter unconst cv::Mat*
dans uncv::Mat*
. Je ne sais pas pourquoi ce n'est pas le cas avec des références... - Je ne suis pas sûr de ce que la question est de savoir, mais si vous vous demandez pourquoi vous obtenez ce contre-intuitive, le comportement, la réponse est que à un certain moment, quelqu'un a décidé que ce serait une bonne idée de la conception
cv::Mat
de cette façon. - J'ai oublié de mentionner que j'ai vu des codes en ligne où const cv::Mat& a été utilisé comme un lisibles à l'aide de rappeler le programmeur qu'il n'est pas censé être changé à l'intérieur de la fonction.
- Ce n'est pas de la coulée références; c'est à l'aide de valeurs, ils se réfèrent.
- Mis à part le fait que je pourrais avoir abusé du mot
cast
, pourquoi le compilateur permetOutput = Input;
quandInput
est const référence etOutput
un non-const de référence, mais pas quandInput
est un pointeur const etOutput
un non-const pointeur? - Parce que l'expression équivalente avec des pointeurs serait *Sortie = *Entrée, qui est valide. La mission est de travailler sur les valeurs visées à, pas les références elles-mêmes.
Vous devez vous connecter pour publier un commentaire.
C'est à cause d'OpenCV utilise Gestion Automatique de la Mémoire.
Cela dit, afin de faire deux
cv::Mat
s point à différentes choses, vous avez besoin d'allouer de la mémoire séparément pour eux. Par exemple, ce qui suit fonctionnera comme prévu:P. S:
cv::Mat
contient unint* refcount
qui pointe vers le compteur de référence. Découvrez Gestion de la mémoire et de comptage de référence pour plus de détails:Différences entre l'envoi de
cv::Mat
,const cv::Mat
,const cv::Mat&
oucv::Mat&
que les arguments d'une fonction:cv::Mat Input
: transmettre une copie deInput
s'en-tête. Son en-tête ne sera pas modifié en dehors de cette fonction, mais peut être changé à l'intérieur de la fonction. Par exemple:const cv::Mat Input
: transmettre une copie deInput
s'en-tête. Son en-tête ne sera pas modifiée à l'extérieur ou à l'intérieur de la fonction. Par exemple:const cv::Mat& Input
: passer une référence deInput
s'en-tête. Garantit queInput
's de l'en-tête ne sera pas modifiée à l'extérieur ou à l'intérieur de la fonction. Par exemple:cv::Mat& Input
: passer une référence deInput
s'en-tête. Les changements deInput
s'en-tête de arriver en dehors et à l'intérieur de la fonction. Par exemple:P. S. 2: je dois souligner que, dans tous les quatre situations (
cv::Mat
,const cv::Mat
,const cv::Mat&
oucv::Mat&
), seul l'accès à la Mat en-tête est sobre, de ne pas les données qu'il points de. Par exemple, vous pouvez modifier ses données dans les quatre situations et de ses données, en effet, à l'extérieur ou à l'intérieur de la fonction:clone
partie donne la "ce que vous voulez". C'est joliment fait. +1const cv::Mat Input
plutôt queconst cv::Mat& Input
?Lorsque vous passez un pointeur intelligent comme une référence, vous pouvez, en théorie, de sauver quelque temps de traitement, depuis pointeur intelligent du constructeur par copie n'est pas invoquée.