Je me demande pourquoi je peux utiliser des variables globales (merci à Chris Drew de m'avoir corrigé) dans les lamdas et pourquoi je n'ai pas besoin de les capturer:

#include <iostream>
#include <vector>
using namespace std;

size_t i = 0;
vector<int> v = {1,2,3};

int main()
{
    auto lambda = [](){i = v.size();};
    lambda();
    cout << i << endl;

    return EXIT_SUCCESS;
}

Dans cet exemple de travail minimum, j'accède à size_t et au vecteur sans les capturer. J'aurais dû le faire s'ils étaient déclarés dans la méthode principale. Pourquoi en est-il ainsi et comment puis-je copier le size_t et le vecteur? J'ai essayé d'utiliser [=] comme liste de capture mais cela ne copie pas v et i.

1
Bambino 24 janv. 2017 à 16:39

4 réponses

Meilleure réponse

Une façon de capturer une variable globale par valeur consiste à utiliser C ++ 14 lambda généralisé captures:

#include <iostream>
#include <vector>

size_t i = 0;
std::vector<int> v = {1,2,3};

int main() {
    auto lambda = [myi = i, myv = v]()mutable{myi = myv.size();};
    lambda();
    std::cout << i << std::endl;
}

Démo en direct.

3
Chris Drew 24 janv. 2017 à 14:56

Les lambdas ont accès aux variables globales et aux variables statiques dans une classe sans les capturer explicitement. S'il s'agissait d'une variable locale, votre programme serait mal formé.

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    size_t i = 0;
    vector<int> v = {1,2,3};
    auto lambda = [](){i = v.size();};   //Error, 
    lambda();
    cout << i << endl;

    return EXIT_SUCCESS;
}

Comme vu ici

Idem avec les variables statiques dans une classe:

#include <iostream>
#include <vector>
using namespace std;

struct S{
    void touch(){ []{ k = 89; }(); }
    static int getK(){ return k; }
private:
    static int k;
};

int S::k = 0;


int main()
{
    S s;
    std::cout << S::getK() << std::endl;
    s.touch();
    std::cout << S::getK() << std::endl;
}

Comme vu Ici

2
WhiZTiM 24 janv. 2017 à 13:49

Dans votre cas, i et v sont des variables globales, accessibles à l'ensemble de l'UT.

Comme vous avez demandé comment les capturer par valeur, je pense que vous devriez pouvoir les capturer en utilisant à la fois [=] ou en listant les variables [i, v], mais cela entraînerait une erreur, car elles seront lues- uniquement et vous affectez à i à l'intérieur du corps lambda.

Option 1:
capturer i par ref et v par valeur (si cela a du sens ...):

#include <iostream>  
#include <vector>  
using namespace std;
int main() {
    size_t i = 0;
    vector<int> v = {1,2,3};
    auto lambda = [&i,v](){i = v.size();};
    lambda();
    cout << i << endl;

    return EXIT_SUCCESS; }

http://ideone.com/fkn4za

Option 2:
utilisez un lambda mutable et capturez les deux par valeur (cela a encore moins de sens).
C'est à dire. voir cette question sur SO.
Veuillez noter que dans ce cas également i sera capturé par valeur, donc le i global ne sera pas attribué, restant à la valeur == 0.

http://ideone.com/qwlFVv

2
Community 23 mai 2017 à 12:00

Votre lambda est fondamentalement converti en foncteur, c'est la même chose que:

#include <iostream>
#include <vector>
using namespace std;

size_t i = 0;
vector<int> v = {1,2,3};

struct lambda
{
  void operator()() { i = v.size(); }
};

int main()
{
    lambda x;
    x();
    cout << i << endl;

    return EXIT_SUCCESS;
}

Comme vous pouvez le voir, lambda peut parfaitement accéder à n'importe quelle variable globale, c'est même dans son nom, la variable est globalement accessible.

Si i et v étaient locaux de main(), nous aurions un problème et nous devions les capturer.

2
Sombrero Chicken 24 janv. 2017 à 13:47