Ссылка бесполезна в std :: bind? - PullRequest
1 голос
/ 23 апреля 2020
//example

void f(int &n1, int& n2)
{
    n1++;
    n2++;
}
int main()
{
    int n1 = 1, n2 = 2;
    auto bound1 = std::bind(&f, n1, std::ref(n2));
    bound1();    // 1 3
    std::cout << n1  << n2 << endl;
    auto bound2 = std::bind(&f, std::placeholders::_1, std::ref(n2)); // 2 4
    bound2(n1);
    std::cout << n1  << n2 << endl;
}

Мой первый вопрос будет касаться ссылки в функции f, неправильно ли делать std::bind для функции, которая получает параметр по ссылке?

Поскольку в приведенном выше коде значение n1 не изменяется. В конце концов я вижу, если я поставлю std::placeHolders::_1, значение n1 изменится. Это мой второй вопрос std::placeHolders call std::ref?

Я знаю, что название не очень наводит на мысль ...

Ответы [ 3 ]

2 голосов
/ 23 апреля 2020

неправильно ли выполнять std :: bind для функции, которая получает параметр по ссылке?

Это допустимо ... но, как вы заметили, n1 не изменяется, что может быть удивительно.

Различие легче определить с помощью лямбда-ИМО:

[n1, &n2](){ f(n1, n2); } против [&n1, &n2](){ f(n1, n2); }

Это мой второй вопрос std :: placeHolders вызывает std :: ref?

Нет, но bind должен обрабатывать как placeholder типы, так и reference_wrapper типы особенно.

2 голосов
/ 23 апреля 2020

неправильно ли выполнять std :: bind для функции, которая получает параметр по ссылке?

Нет, это не так.

Связанные аргументы всегда сохраняются по значению. Поэтому, если вы хотите, чтобы связанный аргумент ссылался на внешний объект, необходимо использовать ссылочную обертку.

Это мой второй вопрос: вызов std :: placeHolders std :: ref?

Аргумент, переданный связанной функции, передается напрямую, без сохранения по значению. Таким образом, ссылочная оболочка не требуется.

0 голосов
/ 23 апреля 2020

Это как вы говорите.

Если вы не используете std::ref / std::cref или std::placeholder, ваш аргумент копируется.

Затем передается «сохраненный» аргумент посредством ссылки на функцию во время вызова, но это не повлияет на объект, который вы передали на месте вызова.

Это может быть удивительно; вам просто нужно к этому привыкнуть.

Вы можете извлечь его из стандартной формулировки ( в [func.bind.bind]), но, честно говоря, весь этот раздел довольно эзотеричен c.

То же самое относится и к std::thread - вы должны использовать std::ref, если вы хотите нести ссылки на всем протяжении.

Обе std::thread и std::bind обычно выполняют функцию, на которую ссылаются «позже», то есть вне текущей области (ваш пример для std::bind необычен; обычно вы просто вызываете f прямо там), поэтому безопаснее сделать это, поэтому вам нужно явно скажите «возьмите ссылку на эту вещь, если хотите этого. Это может или не может быть обоснованием дизайнеров.

...