извините за такой длинный вопрос, но я стараюсь быть максимально ясным.Это как-то следует моему предыдущему вопросу о строках в C ++ .Я пытаюсь выяснить, как я могу вернуть std :: string из функции без избыточного выделения памяти, , не полагаясь на NRVO .Причины, по которым я не хочу полагаться на NRVO:
- , он не поддерживается компилятором, который мы сейчас используем
- , даже если он поддерживается, он не всегда может быть включенв режиме отладки
- в некоторых случаях может произойти сбой ( пример )
Обратите внимание, что мне нужно решение, совместимое с C ++ 03 (без C ++0x rvalue ссылок, таким образом, к сожалению ...)
Простейший способ сделать это - передача по ссылке и выполнить std :: swap, например
void test(std::string& res)
{
std::string s;
//...
res.swap(s);
}
Но это более естественнои часто более удобно возвращать по значению, чем передавать по ссылке, поэтому я хочу добиться следующего:
std::string test()
{
std::string s;
//...
return SOMETHING(s);
}
В идеале это просто сделало бы swap
с "возвращаемым значением", но я нене вижу, как это сделать в C ++.Уже есть auto_ptr, который перемещается вместо копирования, и я мог бы на самом деле использовать auto_ptr<string>
, но я бы хотел избежать динамического выделения самого строкового объекта.
Моя идея состоит в том, чтобы как-то «пометить» строкуобъект, который возвращается из функции, чтобы разрешить перемещение своих данных при вызове конструктора копирования по возвращении.Итак, я получил этот код, который делает именно то, что я хочу:
struct Str
{
struct Moveable
{
Str & ref;
explicit Moveable(Str & other): ref(other) {}
};
Str() {}
Str(const std::string& other) : data(other) {} // copy
Str(Moveable& other) { data.swap(other.ref.data); } // move
Moveable Move()
{
return Moveable(*this);
}
std::string data;
};
Str test()
{
Str s;
//...
return s.Move(); // no allocation, even without NRVO
}
Итак ... Имеет ли все это смысл, или есть некоторые серьезные проблемы, которые я упускаю?(Я не уверен, если нет проблемы жизни, например).Может быть, вы уже видели такую идею в библиотеке (книга, статья ...) и могли бы дать мне ссылку на нее?
РЕДАКТИРОВАТЬ: Как заметил @rstevens, этот код специфичен для MSVC и выиграл 't компилируется под g ++, который не любит временную неконстантность.Это является проблемой, но давайте просто предположим, что эта реализация зависит от MSVC.