2013-05-25 2 views
1

код ниже:Конкатенация два переехал строки

#include <iostream> 
#include <string> 
using namespace std; 

int main() { 
    string s1 = "hello"; 
    string s2 = "my"; 
    string s3 = "world"; 
    string s4; 
    s4 = move(s1) + move(s2) + move(s3); 
    cout << "s4(" << s4 << ") = s1(" << s1 << ") + s2(" << s2 << ") + s3(" << s3 << ")"<< endl; 
} 

дает следующий результат:

s4(hellomyworld) = s1() + s2(my) + s3(world) 

Можете ли вы объяснить, что происходит? (Испытано с XCode 4.6.1)

EDIT: Я ожидал увидеть: s4(hellomyworld) = s1() + s2() + s3()

+0

Обращайтесь к описанию того, что вы ожидали вместо этого. Ваше понимание может быть не таким, как понимание (и, действительно, потому, что вы здесь задаете вопрос, чтобы решить вашу путаницу, возможно, это не так! _) –

ответ

4

Предполагаете, вы ожидали s4(hellomyworld) = s1() + s2() + s3().

Прежде всего, движение оставляет исходный объект в «действительном состоянии с неопределенным значением» ([C++11: 21.4.2/2]) —, то есть вы не можете претендовать на то, что значение строки будет после того, как вы перейдете от него.

Во-вторых, std::move является неправильным выражением, в этом оно ничего не делает.. Движение осуществляется путем замены вещей вокруг, и нет никакой гарантии, что ваш string operator+ сделает что-нибудь в этом роде (см. Ответ jmihalicza для примера реализации); все std::move действительно получает ссылку на rvalue, что может быть перемещен из.

[C++11: 21.4.6.3/1] говорит о std::basic_string& assign(basic_string&& str) noexcept (который является функцией вы действительно вызова, когда вы будете следовать все сухари из operator+), что «действительная реализация swap(str)», но это не означает, что своп имеет произойти ,

1

s4 = move(s1) + move(s2) + move(s3) фактически operator=(s4, operator+(operator+(move(s1), move(s2)), move(s3)); Реализация operator+ не требуется, чтобы изменить его RValue аргумент, но допускается. Предположительно, реализация такова:

string operator+(string&& left, string&& right) 
{ 
    string result(left); 
    return result += right; 
} 

, где право читается.

+0

Зачем вам создавать временную переменную 'result', если вы собираетесь вернуть ссылку? (обратите внимание, что стандарт не возвращает ссылку там) –

+0

Спасибо за исправление, я исправил фрагмент кода – jmihalicza

+0

Хмм, если я не ошибаюсь, ваша новая версия предотвращает копирование ... –

0
template<class _CharT, class _Traits, class _Allocator> 
_LIBCPP_INLINE_VISIBILITY inline 
basic_string<_CharT, _Traits, _Allocator> 
operator+(basic_string<_CharT, _Traits, _Allocator>&& __lhs, basic_string<_CharT, _Traits, _Allocator>&& __rhs) 
{ 
    return _VSTD::move(__lhs.append(__rhs)); 
} 

Так кажется, что во время конкатенации __rhs s остались без изменений. После того, как вся строка накапливается при s1, присваивание перемещения s4 опустошено s1.

Смежные вопросы