어떤 class의 멤버변수로 string을 넘겨주어야 할 경우, 크게 두 가지 옵션이 있다.
1. const reference로 받은 뒤 멤버변수에 복사한다.
2. value로 받은 뒤 std::move를 사용해서 멤버변수를 초기화 시킨다.
이론상 2번 방법이 좀 더 효과적이라고 생각했는데,
실제 benchmark 결과 1번이 더 빠른 것을 확인했다.
Function parameter로 받아은 값을 class member variable로 설정해야 하는 경우
이 경우에는 외부의 값을 받아서 class member variable로 설정해야 한다는 점에서 특수성이 생긴다.
(주로 constructor에서 이런 작업들이 일어난다)
(class member variable이 어떤 데이터의 reference variable이 아닌 경우)
이 경우에는 const reference 보다 std::move를 사용하는 편이 더 합리적일 수 있다.
▶ const reference로 받아서 멤버에 복사하게 될 경우
SomeConstructor(const T& param) : param_(param) {}
- lvalue를 받았을 경우: lvalue가 argument(reference)로 바인드 되고, 이 값이 멤버변수로 copy 된다.
- rvalue를 받았을 경우: rvalue가 argument로 바인드 되고, 이 값이 멤버변수로 copy 된다.
▶ std::move를 사용할 경우
SomeConstructor(T param) : param_(std::move(param)) {}
- lvalue를 받았을 경우: lvalue가 argument로 copy 되고, 이 값이 멤버변수로 move 된다.
- rvalue를 받았을 경우: rvalue가 argument로 move 되고, 이 값이 멤버변수로 다시 move 된다.
결국 const reference의 (1), (2)번 경우와 std::move의 (1)번 경우는 모두 복사가 1회 일어나는데,
std::move의 (2)번의 경우 copy가 일어나지 않는다는 장점이 있다.
String과 같이 rvalue를 직접 넣어주는 경우가 많을 때는 위와 같은 방식이 더 효율적이라고 할 수 있다.
(Clang tidy에서도 위와 같은 방법을 권장한다.)
실제 Benchmark 결과
#include <string>
#include <utility>
class A
{
public:
A(const std::string& str) : str_(str) {};
private:
std::string str_;
};
class B
{
public:
B(std::string str) : str_(std::move(str)) {};
private:
std::string str_;
};
static void ReferenceLValue(benchmark::State& state)
{
for (auto _ : state)
{
std::string str("LValue");
A a(str);
benchmark::DoNotOptimize(str);
benchmark::DoNotOptimize(a);
}
}
BENCHMARK(ReferenceLValue);
static void ReferenceRValue(benchmark::State& state)
{
for (auto _ : state)
{
A a("RValue");
benchmark::DoNotOptimize(a);
}
}
BENCHMARK(ReferenceRValue);
static void MoveLValue(benchmark::State& state)
{
for (auto _ : state)
{
std::string str("LValue");
B b(str);
benchmark::DoNotOptimize(str);
benchmark::DoNotOptimize(b);
}
}
BENCHMARK(MoveLValue);
static void MoveRValue(benchmark::State& state)
{
for (auto _ : state)
{
B b("RValue");
benchmark::DoNotOptimize(b);
}
}
BENCHMARK(MoveRValue);
반응형
'Programming > Modern c++' 카테고리의 다른 글
string literal은 어디에 저장될까? (0) | 2022.06.13 |
---|---|
std::string_view (0) | 2022.06.13 |
C++ 표준 난수 라이브러리 <random> (0) | 2022.04.07 |