#ifndef STRING_INCLUDED #define STRING_INCLUDED 1 #include #include struct string; std::ostream& operator << ( std::ostream& , const string& s ); struct string { size_t len; char *p; string( const char* s ) : len{ strlen(s) }, p{ new char[ len ] } { for( size_t i = 0; i < len; ++ i ) p[i] = s[i]; } string( const string& s ) : len{ s. len }, p{ new char[ s.len ] } { std::cout << "CC " << s << "\n"; for( size_t i = 0; i < len; ++ i ) p[i] = s.p[i]; } string( string&& s ) : len{ s. len }, p{ s.p } { std::cout << "Rvalue-CC " << s << "\n"; s.p = // new char[0]; // nullptr; nullptr; // See in slides why this is the same. s.len = 0; } string( const string& s1, const string& s2 ) : len{ s1. len + s2. len }, p{ new char[ s1. len + s2. len ] } { for( size_t i = 0; i < s1. len; ++ i ) p[i] = s1.p[i]; for( size_t i = 0; i < s2. len; ++ i ) p[ i + s1. len ] = s2.p[i]; } string( std::initializer_list< char > init ) : len{ init. size( ) }, p{ new char[ init. size( ) ] } { size_t i = 0; for( char c : init ) p [ i ++ ] = c; } #if 0 void operator = ( const string& s ) { if( p != s.p ) { delete[] p; len = s. len; p = new char[ len ]; for( size_t i = 0; i < len; ++ i ) p[i] = s.p[i]; } } #endif void operator = ( string&& s ) { std::cout << "Rvalue assignment " << s << "\n"; std::swap( s. len, len ); std::swap( s. p, p ); } void operator = ( const string& s ) { std::cout << "not Rvalue assignment " << s << "\n"; *this = string(s); } size_t length( ) const { return len; } ~string( ) { std::cout << "destroying " << *this << "\n"; delete[] p; } }; inline string operator + ( const string& s1, const string& s2 ) { string s = string( s1, s2 ); char c = getchar( ); // Needed to deceive the compiler, so that it won't use // the return value optimization. if( c == 'x' ) return s; else return string( s2, s1 ); } inline std::ostream& operator << ( std::ostream& out, const string& s ) { for( size_t i = 0; i != s. len; ++ i ) out << s.p[i]; // std::cout << "length = " << s. length( ) << "\n"; return out; } #endif