Consider the case when "whole" objects with move semantics enabled are returned from functions, as with std::basic_string<>
:
std::wstring build_report() const
{
std::wstring report;
...
return report;
}
Can I then realistically be expected to make the "best" choice whether to use the returned string with move semantics, as in
const std::wstring report(std::move(build_report()));
or if I should rely on (N)RVO to take place with
const std::wstring report(build_report());
or even bind a const reference to the temporary with
const std::wstring& report(build_report());
What scheme is there to make a deterministic choice of these options, if any?
EDIT 1: Note that the usage of std::wstring
above is just an example of a move semantics enabled type. It just as well be swapped for your arbitrary_large_structure
. :-)
EDIT 2: I checked the generated assembly when running a speed-optmized release build in VS 2010 of the following:
std::wstring build_report(const std::wstring& title, const std::wstring& content)
{
std::wstring report;
report.append(title);
report.append(content);
return report;
}
const std::wstring title1(L"title1");
const std::wstring content1(L"content1");
const std::wstring title2(L"title2");
const std::wstring content2(L"content2");
const std::wstring title3(L"title3");
const std::wstring content3(L"content3");
int _tmain(int argc, _TCHAR* argv[])
{
const std::wstring report1(std::move(build_report(title1, content1)));
const std::wstring report2(build_report(title2, content2));
const std::wstring& report3(build_report(title3, content3));
...
return 0;
}
The 2 most interesting outcomes:
- Explicitly calling
std::move
forreport1
to use the move constructor triples the instruction count. - As noted by James McNellis in his answer below,
report2
andreport3
does indeed generate identical assembly with 3 times fewer instructions than explicitly callingstd::move
.