C++, copy elision, MSVC

bleyman

Он там вообще как бы должен поддерживаться, или как обычно, сделали для галочки?
Типа, код:

#include <stdlib.h>
#include <stdio.h>
#include <string>

using std::string;

struct C
{
string s;
C(const string & a_s) : s(a_s) { printf("C::ctor(%s)\n", s.c_str()); }
C(const C & c) : s(c.s) { printf("C::cctor(%s)\n", s.c_str()); }
~C() { printf("C::dtor(%s)\n", s.c_str()); }
};

C f(C c1)
{
return C("retval from " + c1.s);
}

int main()
{
C c1 = f(C("arg"));
printf("Done!\n");
return 0;
}

Copy elision работает отлично, копи конструктор не вызывается ни разу. А вот если следуя тем же заветам Херба Саттера поменять C(const string & a_s) на C(string a_s), то всё, в Вижуал Студии 2012 копи конструкторы овладевают повсеместно.
Что интересно, named return value elision продолжает работать как бы, то есть если поменять кодэ внутри функции на

C c("retval from " + c1.s);
return c;

то один копи конструктор исчезает.
gcc (даже довольно древний 4.3.2) работает ОК: http://ideone.com/XcAgiH
Ну и как это понимать? Мне казалось, что copy elision должен работать по неформальным, но довольно простым правилам. А тут какая-то чорная магея, от типа параметра в конструкторе внезапно отрубается всё кроме NRVE. Это потому что они мудаки, и под вижуалстудией надеятся на copy elision не следует? Или может у них наоборот шибко умный оптимизатор который её иногда отключает чтобы, я не знаю, сэкономить на чём-нибудь?

Maurog

надеятся на copy elision не следует?
надеяться на copy elision вообще не надо, и неважно под каким компилятором
надеяться и полагаться надо на move конструкторы, они работают по формальным правилам и решают все описанные проблемы (если я правильно понял зачем это вам)
еще не очень понял откуда в VS2012 будет много копирований при передачи std::string по значению, ведь там реализована move семантика

bleyman

еще не очень понял откуда в VS2012 будет много копирований при передачи std::string по значению, ведь там реализована move семантика
Ты не понял. Передача строки (как параметра) по значению ВНЕЗАПНО отрубает всё copy elision кроме NRVE (просто RVE тоже отрубает).
надеяться на copy elision вообще не надо, и неважно под каким компилятором
надеяться и полагаться надо на move конструкторы, они работают по формальным правилам и решают все описанные проблемы (если я правильно понял зачем это вам)
Нуууу, для этого же нужен C++11, и все эти move constructors имплементировать, и надеяться что они везде имплементированы, и в конце концов это тупо менее эффективно. То есть я понимаю что вызвать move ctor для возвращаемого вектора более эффективно чем copy, но не вызывать вообще никакого-то ещё более эффективно!

amkharchenko

Схожий баг: http://connect.microsoft.com/VisualStudio/feedback/details/...
Closed as By Design ггг
Оставить комментарий
Имя или ник:
Комментарий: