сумма квадрата каждого элементы в векторе с помощью for_each

кто-либо может сказать мне преимущество синхронизированного метода по синхронизируемому блоку с примером? Спасибо.

нет ясного преимущества использования синхронизированного метода по блоку.

, Возможно, единственный (но я не назвал бы это преимуществом) является Вами, не должны включать Метод ссылки на объект this.

:

public synchronized void method() { // blocks "this" from here.... 
    ...
    ...
    ...
} // to here

Блок:

public void method() { 
    synchronized( this ) { // blocks "this" from here .... 
        ....
        ....
        ....
    }  // to here...
}

Посмотрите? Никакое преимущество вообще.

Блоки делают , имеют преимущества перед методами, хотя, главным образом в гибкости, потому что можно использовать другой объект в качестве блокировки, тогда как синхронизация метода заблокировала бы весь объект.

Сравните:

// locks the whole object
... 
private synchronized void someInputRelatedWork() {
    ... 
}
private synchronized void someOutputRelatedWork() {
    ... 
}

по сравнению с [1 116]

// Using specific locks
Object inputLock = new Object();
Object outputLock = new Object();

private void someInputRelatedWork() {
    synchronized(inputLock) { 
        ... 
    } 
}
private void someOutputRelatedWork() {
    synchronized(outputLock) { 
        ... 
    }
}

Также, если метод растет, можно все еще сохранить синхронизируемый раздел разделенным:

 private void method() {
     ... code here
     ... code here
     ... code here
    synchronized( lock ) { 
        ... very few lines of code here
    }
     ... code here
     ... code here
     ... code here
     ... code here
}
10
задан Jon Seigel 15 May 2010 в 21:01
поделиться

6 ответов

Используйте std :: accumulate

#include <vector>
#include <numeric>

// functor for getting sum of previous result and square of current element
template<typename T>
struct square
{
    T operator()(const T& Left, const T& Right) const
    {   
        return (Left + Right*Right);
    }
};

void main()
{
    std::vector <int> v1;
    v1.push_back(1);
    v1.push_back(2);
    v1.push_back(3);
    v1.push_back(4);

    int x = std::accumulate( v1.begin(), v1.end(), 0, square<int>() );
    // 0 stands here for initial value to which each element is in turn combined with
    // for our case must be 0.
}

Вы можете эмулировать std :: accumulate, как в хороший ответ GMan , но я считаю, что использование std :: accumulate будет сделайте ваш код более читабельным, потому что он был разработан для таких целей. Вы можете найти больше стандартных алгоритмов здесь .

21
ответ дан 3 December 2019 в 13:12
поделиться

Нет, не используйте std :: accumulate (), используйте std :: inner_product (). Функтор не требуется.

#include <vector>
#include <numeric>

void main()
{
    std::vector <int> v1;
    v1.push_back(1);
    v1.push_back(2);
    v1.push_back(3);
    v1.push_back(4);

    int x = std::inner_product( v1.begin(), v1.end(), v1.begin(), 0 );
}
37
ответ дан 3 December 2019 в 13:12
поделиться

for_each возвращает (копию) функтора, который он использовал. Итак, что-то вроде этого:

#include <algorithm>
#include <vector>
#include <iostream>

template <typename T>
class square_accumulate
{
public:
    square_accumulate(void) :
      _sum(0)
      {
      }

      const T& result(void) const
      {
          return _sum;
      }

      void operator()(const T& val)
      {
          _sum += val * val;
      }

private:
    T _sum;
};

int main(void)
{
    int arr[] = {1,2,3,4};
    std::vector<int> a (arr ,arr + sizeof(arr)/sizeof(arr[0]));

    int sum = std::for_each(a.begin(), a.end(), square_accumulate<int>()).result();

    std::cout << "sum of the square of the element is " << sum << std::endl;
}

Однако, как показывают другие ответы, std :: accumulate - лучший способ.

7
ответ дан 3 December 2019 в 13:12
поделиться

Не используйте for_each () для этого, используйте Accumulate () из заголовок:

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

struct accum_sum_of_squares {
    // x contains the sum-of-squares so far, y is the next value.
    int operator()(int x, int y) const {
        return x + y * y;
    }
};

int main(int argc, char **argv) {
    int a[] = { 4, 5, 6, 7 };

    int ssq = accumulate(a, a + sizeof a / sizeof a[0], 0, accum_sum_of_squares());
    cout << ssq << endl;
    return 0;
}

По умолчанию аккумулятор () суммирует элементы, но вы можете предоставить свою собственную функцию или функтор, как мы делаем здесь, и выполняемая им операция не требует быть ассоциативным - второй аргумент всегда является следующим элементом, с которым нужно работать. Эта операция иногда называется reduce на других языках.

Вы можете использовать простую функцию вместо функтора accum_sum_of_squares , или для еще большей универсальности вы можете сделать accum_sum_of_squares шаблон класса, который принимает любой числовой тип.

t используйте для этого for_each () , используйте accumulate () из заголовка :

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

struct accum_sum_of_squares {
    // x contains the sum-of-squares so far, y is the next value.
    int operator()(int x, int y) const {
        return x + y * y;
    }
};

int main(int argc, char **argv) {
    int a[] = { 4, 5, 6, 7 };

    int ssq = accumulate(a, a + sizeof a / sizeof a[0], 0, accum_sum_of_squares());
    cout << ssq << endl;
    return 0;
}

Поведение по умолчанию для accumulate () предназначен для суммирования элементов, но вы можете предоставить свою собственную функцию или функтор, как мы делаем здесь, и выполняемая им операция не обязательно должна быть ассоциативной - второй аргумент всегда является следующим элементом, над которым нужно работать. Эта операция иногда называется reduce на других языках.

Вы можете использовать простую функцию вместо функтора accum_sum_of_squares , или, для еще большей универсальности, вы можете сделать accum_sum_of_squares шаблон класса, который принимает любой числовой тип.

t используйте для этого for_each () , используйте accumulate () из заголовка :

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

struct accum_sum_of_squares {
    // x contains the sum-of-squares so far, y is the next value.
    int operator()(int x, int y) const {
        return x + y * y;
    }
};

int main(int argc, char **argv) {
    int a[] = { 4, 5, 6, 7 };

    int ssq = accumulate(a, a + sizeof a / sizeof a[0], 0, accum_sum_of_squares());
    cout << ssq << endl;
    return 0;
}

Поведение по умолчанию для accumulate () предназначен для суммирования элементов, но вы можете предоставить свою собственную функцию или функтор, как мы делаем здесь, и выполняемая им операция не обязательно должна быть ассоциативной - второй аргумент всегда является следующим элементом, над которым нужно работать. Эта операция иногда называется reduce на других языках.

Вы можете использовать простую функцию вместо функтора accum_sum_of_squares , или, для еще большей универсальности, вы можете сделать accum_sum_of_squares шаблон класса, который принимает любой числовой тип.

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

struct accum_sum_of_squares {
    // x contains the sum-of-squares so far, y is the next value.
    int operator()(int x, int y) const {
        return x + y * y;
    }
};

int main(int argc, char **argv) {
    int a[] = { 4, 5, 6, 7 };

    int ssq = accumulate(a, a + sizeof a / sizeof a[0], 0, accum_sum_of_squares());
    cout << ssq << endl;
    return 0;
}

По умолчанию аккумулятор () суммирует элементы, но вы можете предоставить свою собственную функцию или функтор, как мы делаем здесь, и выполняемая им операция не обязательно должна быть ассоциативной - второй аргумент всегда следующий элемент, с которым нужно работать. Эта операция иногда называется reduce на других языках.

Вы можете использовать простую функцию вместо функтора accum_sum_of_squares , или для еще большей универсальности вы можете сделать accum_sum_of_squares шаблон класса, который принимает любой числовой тип.

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

struct accum_sum_of_squares {
    // x contains the sum-of-squares so far, y is the next value.
    int operator()(int x, int y) const {
        return x + y * y;
    }
};

int main(int argc, char **argv) {
    int a[] = { 4, 5, 6, 7 };

    int ssq = accumulate(a, a + sizeof a / sizeof a[0], 0, accum_sum_of_squares());
    cout << ssq << endl;
    return 0;
}

По умолчанию функция accumulate () суммирует элементы, но вы можете предоставить свою собственную функцию или функтор, как мы здесь, и выполняемая им операция не обязательно должна быть ассоциативной - второй аргумент всегда следующий элемент, с которым нужно работать. Эта операция иногда называется reduce на других языках.

Вы можете использовать простую функцию вместо функтора accum_sum_of_squares , или, для еще большей универсальности, вы можете сделать accum_sum_of_squares шаблон класса, который принимает любой числовой тип.

4
ответ дан 3 December 2019 в 13:12
поделиться

В качестве общего решения такой проблемы с STL: вместо передачи функции вы можете передать функтор - например, экземпляр любого класса, реализующего оператор () . Это намного лучше, чем полагаться на глобальные переменные, поскольку указанный экземпляр может сохранять и обновлять свое собственное состояние! Вы можете думать об этом как о разновидности «утиного набора текста во время компиляции»: универсальное программирование не ограничивает вас передачей «функции» в этом месте, всего, что «ведет себя как функция» (т.е. имеет правильный оператор () ) тоже подойдет! -)

3
ответ дан 3 December 2019 в 13:12
поделиться

std :: for_each предназначен для выполнения каких-либо действий с каждым элементом . Если вы хотите получить результат вычисления всех элементов, есть std :: accumulate . Если вам нужно поведение Haskell map , используйте std :: transform .

Вы можете злоупотреблять любым из этих трех, чтобы делать то же самое, что и любые другие, поскольку в конечном итоге они просто повторяют итератор (за исключением формы transform , которая принимает на вход два итератора. Дело в том, что for_each не является заменой map / fold - это должно быть сделано путем преобразования / накопления - хотя в C ++ изначально нет чего-то, что выражало бы концепцию map / fold, а также Haskell. - но и gcc, и VC ++ поддерживают OpenMP, который имеет гораздо лучший аналог в #pragma omp parallel for .

Inject в Ruby намного ближе к вызову for_each с полноценным функтором, например GMan , описанным выше. Лямбда-функции с захватом переменных в C ++ 0X сделают поведение между двумя языками еще более похожим:

int main(void)
{
    int arr[] = {1,2,3,4};
    std::vector<int> a (arr ,arr + sizeof(arr)/sizeof(arr[0]));

    int sum = 0;
    std::for_each(a.begin(), a.end(), [&](int i) { sum += i*i;} );

    std::cout << "sum of the square of the element is " << sum << std::endl;
}
3
ответ дан 3 December 2019 в 13:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: