std :: vector의 집계 목록 초기화는 이동 이 더 적합 할 때 복사 초기화를 수행 한다는 것을 알았습니다 . 동시에 여러 emplace_backs가 원하는 것을 수행합니다.
나는 템플릿 함수를 작성하는이 불완전한 해결책을 생각 해낼 수 있었다 init_emplace_vector
. 그러나 명시 적이 지 않은 단일 값 생성자에 대해서만 최적입니다 .
template <typename T, typename... Args>
std::vector<T> init_emplace_vector(Args&&... args)
{
std::vector<T> vec;
vec.reserve(sizeof...(Args)); // by suggestion from user: eerorika
(vec.emplace_back(std::forward<Args>(args)), ...); // C++17
return vec;
}
질문
std :: vector를 최대한 효율적으로 초기화 하려면 emplace_back을 사용해야 합니까?
// an integer passed to large is actually the size of the resource
std::vector<large> v_init {
1000, // instance of class "large" is copied
1001, // copied
1002, // copied
};
std::vector<large> v_emplaced;
v_emplaced.emplace_back(1000); // moved
v_emplaced.emplace_back(1001); // moved
v_emplaced.emplace_back(1002); // moved
std::vector<large> v_init_emplace = init_emplace_vector<large>(
1000, // moved
1001, // moved
1002 // moved
);
산출
클래스 large
는 복사 / 이동 (아래 구현)에 대한 정보를 생성하므로 내 프로그램의 출력은 다음과 같습니다.
- initializer
large copy
large copy
large copy
- emplace_back
large move
large move
large move
- init_emplace_vector
large move
large move
large move
대규모 클래스 구현
내 구현 large
은 단순히 복사 / 이동에 대해 경고하는 큰 리소스를 보유하는 복사 가능한 / 이동 가능한 유형입니다.
struct large
{
large(std::size_t size) : size(size), data(new int[size]) {}
large(const large& rhs) : size(rhs.size), data(new int[rhs.size])
{
std::copy(rhs.data, rhs.data + rhs.size, data);
std::puts("large copy");
}
large(large&& rhs) noexcept : size(rhs.size), data(rhs.data)
{
rhs.size = 0;
rhs.data = nullptr;
std::puts("large move");
}
large& operator=(large rhs) noexcept
{
std::swap(*this, rhs);
return *this;
}
~large() { delete[] data; }
int* data;
std::size_t size;
};
편집하다
예약을 사용하면 복사 또는 이동이 없습니다. large::large(std::size_t)
생성자 만 호출됩니다. 진정한 직장.
std::array
.
operator=
소스를 파괴하는 아주 특이한 예기치 않은 문제가 발생할 수 있습니다.
init_emplace_vector
개선 할 수vec.reserve(sizeof...(Args))
operator=
은 소스를 파괴하지 않습니다. 복사 스왑 관용구입니다.
std::initializer_list
.