std :: transform을 사용하여 목록에있는 기존 값에 일부 값을 추가했습니다. 아래의 코드는 잘 작동하지만 변환을 실행할 때 복사 생성자 (프로그램의 출력 참조)에 대한 모든 호출을 피할 수 있는지 궁금합니다. 방금 코드를 해킹하고 for 루프가 Base의 + = 연산자를 명시 적으로 호출하면 복사 구성이 실행되지 않고 값이 더 효율적으로 변경됩니다.std :: transform이 생성자를 사용하는 이유는 무엇입니까?
복사를 구성하는 대신 Base의 + = 연산자를 변형 할 수 있습니까? increment<Type>
에 집중해야합니까?
프로그램 :
#include <iostream>
#include<list>
#include <algorithm>
#include <iterator>
template<class T>
class Base;
template<class T>
std::ostream& operator << (std::ostream& os, const Base<T>& b);
template<class T>
class Base
{
private:
T b_;
public:
typedef T value_type;
Base()
:
b_()
{ std::cout << "Base::def ctor" << std::endl; }
Base (const T& b)
:
b_(b)
{ std::cout << "Base::implicit conversion ctor: " << b_ << std::endl; }
const T& value()
{
return b_;
}
const Base operator+(const Base& b) const
{
std::cout << "Base operator+ " << std::endl;
return Base(b_ + b.b_);
}
const Base& operator+=(const T& t)
{
b_ += t;
return *this;
}
friend std::ostream& operator<< <T> (std::ostream& os, const Base<T>& b);
};
template<class T>
std::ostream& operator<< (std::ostream& os, const Base<T>& b)
{
os << b.b_;
return os;
}
template<class Type>
class increment
{
typedef typename Type::value_type T;
T initial_;
public:
increment()
:
initial_()
{};
increment(const T& t)
:
initial_(t)
{}
T operator()()
{
return initial_++;
}
};
template<class Container>
void write(const Container& c)
{
std::cout << "WRITE: " << std::endl;
copy(c.begin(), c.end(),
std::ostream_iterator<typename Container::value_type > (std::cout, " "));
std::cout << std::endl;
std::cout << "END WRITE" << std::endl;
}
using namespace std;
int main(int argc, const char *argv[])
{
typedef list<Base<int> > bList;
bList baseList(10);
cout << "GENERATE" << endl;
generate_n (baseList.begin(), 10, increment<Base<int> >(10));
cout << "END GENERATE" << endl;
write(baseList);
// Let's add some integers to Base<int>
cout << "TRANSFORM: " << endl;
std::transform(baseList.begin(), baseList.end(),
baseList.begin(),
bind2nd(std::plus<Base<int> >(), 4));
cout << "END TRANSFORM " << endl;
write(baseList);
// Hacking the code:
cout << "CODE HACKING: " << endl;
int counter = 4;
for (bList::iterator it = baseList.begin();
it != baseList.end();
++it)
{
*it += counter; // Force the call of the operator+=
++counter;
}
write (baseList);
cout << "END CODE HACKING" << endl;
return 0;
}
'std :: for_each'는 증분이 더 나은 술어, 여기서는 IMO입니다. – jrok
팁 주셔서 감사합니다. 답변으로 작성하면 받아 들일 것입니다. – tmaric
나는 완전히 질문에 대답하지 않는다고 생각하므로 코멘트를 남겨 두겠습니다 :'int counter = 4; std :: for_each (baseList.begin(), baseList.end(), [& counter] (int & i) {i + = counter ++;});'C++ 03에 머물고 싶다면 아마도 커스텀 펑터를 호출하고 이것을 'plus_assign'또는 이와 비슷한 방식으로 호출합니다. 나는 당신이 + =에'std :: plus'를 강제로 호출 할 수 있다고 생각하지 않는다. – jrok