std::string::c_str(): потенциальное копирование (было: минусы STL)
От: Mazay Россия  
Дата: 23.08.06 13:17
Оценка:
Здравствуйте, gid_vvp, Вы писали:

_>перечислите, на ваш взгляд, основные минусы STL

_>принимаются только ответы с аргументацией


Строки из STL практически нигде не используются. Используются велосипеды или char*. Ни с тем ни с другим std::string нормально не сопрягается. Главным образом потому, что c_str() возвращает не внутренний буфер, а временный. Лишнее копирование никому не нужно.




24.08.06 07:26: Ветка выделена из темы минусы STL
Автор: gid_vvp
Дата: 23.08.06
— Павел Кузнецов
Главное гармония ...
Re: std::string::c_str(): потенциальное копирование (было: минусы STL)
От: kan_izh Великобритания  
Дата: 23.08.06 13:22
Оценка:
Mazay wrote:

> Строки из STL практически нигде не используются. Используются велосипеды

> или char*. Ни с тем ни с другим std::string нормально не сопрягается.
> Главным образом потому, что c_str() возвращает не внутренний буфер, а
> временный. Лишнее копирование никому не нужно.
На такое vector<char> есть.
Posted via RSDN NNTP Server 2.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[2]: std::string::c_str(): потенциальное копирование (было: минусы STL)
От: Mazay Россия  
Дата: 23.08.06 13:24
Оценка:
Здравствуйте, kan_izh, Вы писали:

_>Mazay wrote:


>> Строки из STL практически нигде не используются. Используются велосипеды

>> или char*. Ни с тем ни с другим std::string нормально не сопрягается.
>> Главным образом потому, что c_str() возвращает не внутренний буфер, а
>> временный. Лишнее копирование никому не нужно.
_>На такое vector<char> есть.

Это не очевидно. Зачем тогда вообще этот std::string ?
Главное гармония ...
Re: std::string::c_str(): потенциальное копирование (было: минусы STL)
От: Aera Беларусь  
Дата: 23.08.06 13:26
Оценка:
Здравствуйте, Mazay, Вы писали:

M>Здравствуйте, gid_vvp, Вы писали:


_>>перечислите, на ваш взгляд, основные минусы STL

_>>принимаются только ответы с аргументацией

M>Строки из STL практически нигде не используются. Используются велосипеды или char*. Ни с тем ни с другим std::string нормально не сопрягается. Главным образом потому, что c_str() возвращает не внутренний буфер, а временный. Лишнее копирование никому не нужно.


Строки не входят в STL, STL — это только контейнеры и алгоритмы.
--
RedApe
Re[3]: std::string::c_str(): потенциальное копирование (было: минусы STL)
От: kan_izh Великобритания  
Дата: 23.08.06 13:32
Оценка: +1
Mazay wrote:

>> > Строки из STL практически нигде не используются. Используются велосипеды

>> > или char*. Ни с тем ни с другим std::string нормально не сопрягается.
>> > Главным образом потому, что c_str() возвращает не внутренний буфер, а
>> > временный. Лишнее копирование никому не нужно.
> _>На такое vector<char> есть.
> Это не очевидно. Зачем тогда вообще этот std::string ?
На остальное. Не вседа и не вся программа состоит из взаимодействия с левыми компонентами char* (не const!), а с
велосипедами вообще ничего не поделаешь в общем случае.
Posted via RSDN NNTP Server 2.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[3]: std::string::c_str(): потенциальное копирование (было: минусы STL)
От: Aera Беларусь  
Дата: 23.08.06 13:33
Оценка:
Здравствуйте, Mazay, Вы писали:

M>Здравствуйте, kan_izh, Вы писали:


_>>Mazay wrote:


>>> Строки из STL практически нигде не используются. Используются велосипеды

>>> или char*. Ни с тем ни с другим std::string нормально не сопрягается.
>>> Главным образом потому, что c_str() возвращает не внутренний буфер, а
>>> временный. Лишнее копирование никому не нужно.
_>>На такое vector<char> есть.

M>Это не очевидно. Зачем тогда вообще этот std::string ?


Для всего остального

Хотя, конечно, следующий код не вызывает у меня энтузиазма
  int len = some.GetTextLength();
  std::vector<char> buffer(len);
  some.GetText(&buffer[0], buffer.size());
  std::string text(&buffer[0], buffer.size());
--
RedApe
Re[4]: std::string::c_str(): потенциальное копирование (было: минусы STL)
От: Mazay Россия  
Дата: 23.08.06 13:41
Оценка:
Здравствуйте, kan_izh, Вы писали:

>> _>На такое vector<char> есть.

>> Это не очевидно. Зачем тогда вообще этот std::string ?
_>На остальное. Не вседа и не вся программа состоит из взаимодействия с левыми компонентами char* (не const!), а с
_>велосипедами вообще ничего не поделаешь в общем случае.

Ахха! Да пусть там хоть в одной строчке конвертация из char*, или wxString, или AnsiString в std::string происходит. Если это требует копирования это может дать тормоза. А мне этого не надо. К тому же не уверен что если сейчас эта строчка одна, то и завтра ещё где-нить надобность в конвертации не выплывет
Главное гармония ...
Re[4]: std::string::c_str(): потенциальное копирование (было: минусы STL)
От: Mazay Россия  
Дата: 23.08.06 13:47
Оценка:
Здравствуйте, Aera, Вы писали:

A>Хотя, конечно, следующий код не вызывает у меня энтузиазма

A>
A>  int len = some.GetTextLength();
A>  std::vector<char> buffer(len);
A>  some.GetText(&buffer[0], buffer.size());
A>  std::string text(&buffer[0], buffer.size());
A>


Я от такого кода чешусь — физически такой penalty не могу переварить. Я ж потом два дня буду больным ходить,если такое придётся написать. Подумать только — ради использования библиотеки — гонять целые строки по памяти. Но самое главное что этим дело скорей всего не закончится и где то будет код типа:

A>
A>  some.SetText(text.c_str());
A>


с ещё одним копированием
Главное гармония ...
Re: std::string::c_str(): потенциальное копирование (было: минусы STL)
От: Шебеко Евгений  
Дата: 23.08.06 15:06
Оценка:
M>Главным образом потому, что c_str() возвращает не внутренний буфер, а временный. Лишнее копирование никому не нужно.

А кто вам такое сказал?

std::string s("kolya petya vasya");
const char* p=s.c_str();
bool equal=p==&*s.begin();
equal=equal;



Так вот equal==true
Re[2]: std::string::c_str(): потенциальное копирование (было: минусы STL)
От: gid_vvp  
Дата: 23.08.06 15:08
Оценка: +2
ШЕ>Так вот equal==true

полагаю что это всётаки зависит от реализации stl
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: std::string::c_str(): потенциальное копирование (было: минусы STL)
От: KBH  
Дата: 23.08.06 15:10
Оценка: +1
Здравствуйте, Шебеко Евгений, Вы писали:

ШЕ>Так вот equal==true


Повезло
Re[2]: std::string::c_str(): потенциальное копирование (было: минусы STL)
От: Smal Россия  
Дата: 23.08.06 15:40
Оценка:
Здравствуйте, Aera, Вы писали:

A>Строки не входят в STL, STL — это только контейнеры и алгоритмы.


Где это написано, что string не входит в STL?
С уважением, Александр
Re[2]: std::string::c_str(): потенциальное копирование (было: минусы STL)
От: Doc Россия http://andrey.moveax.ru
Дата: 23.08.06 15:53
Оценка:
Здравствуйте, Шебеко Евгений, Вы писали:

ШЕ>А кто вам такое сказал?


Недавно тут было
Re: Подводные камни &mdash; strcat и c_str()
Автор: Roman Odaisky
Дата: 16.08.06


std::string::c_str() возвращает указатель типа char const *, содержащий size() + 1 символов, представляющих строку и завершающихся '\0'. Указатель действителен до ближайшего вызова non-const метода.

... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: std::string::c_str(): потенциальное копирование (было: минусы STL)
От: Константин Л. Франция  
Дата: 23.08.06 15:55
Оценка:
Здравствуйте, Mazay, Вы писали:

M>Здравствуйте, gid_vvp, Вы писали:


_>>перечислите, на ваш взгляд, основные минусы STL

_>>принимаются только ответы с аргументацией


M>Строки из STL практически нигде не используются. Используются велосипеды или char*. Ни с тем ни с другим std::string нормально не сопрягается. Главным образом потому, что c_str() возвращает не внутренний буфер, а временный. Лишнее копирование никому не нужно.


а где это там копирование в c_str()?
Re: std::string::c_str(): потенциальное копирование (было: минусы STL)
От: Cyberax Марс  
Дата: 23.08.06 16:03
Оценка:
Mazay wrote:
> Строки из STL практически нигде не используются. Используются велосипеды
> или char*. Ни с тем ни с другим std::string нормально не сопрягается.
> Главным образом потому, что c_str() возвращает не внутренний буфер, а
> временный.
В STL в VS 7/7.1/8 и GCCшной stdlib указатель возвращается на нормальный
буффер.
Posted via RSDN NNTP Server 2.0
Sapienti sat!
Re: std::string::c_str(): потенциальное копирование (было: минусы STL)
От: Константин Л. Франция  
Дата: 23.08.06 16:24
Оценка:
Здравствуйте, Mazay, Вы писали:

M>Здравствуйте, gid_vvp, Вы писали:


_>>перечислите, на ваш взгляд, основные минусы STL

_>>принимаются только ответы с аргументацией


M>Строки из STL практически нигде не используются. Используются велосипеды или char*. Ни с тем ни с другим std::string нормально не сопрягается. Главным образом потому, что c_str() возвращает не внутренний буфер, а временный. Лишнее копирование никому не нужно.


ИМХО хорошим тоном считается немедленное копирование raw char* куда-нибудь при получении его через c_str. Иначе его хранение может сильно испортить настроение.
Re[5]: std::string::c_str(): потенциальное копирование (было: минусы STL)
От: Cyberax Марс  
Дата: 23.08.06 16:40
Оценка:
Mazay wrote:
> A> some.SetText(text.c_str());
> A>
> с ещё одним копированием
Нет тут копирования во всех реализациях STL которые я знаю. С чего оно
должно появится?
Posted via RSDN NNTP Server 2.0
Sapienti sat!
Re[3]: std::string::c_str(): потенциальное копирование (было: минусы STL)
От: Шебеко Евгений  
Дата: 23.08.06 17:10
Оценка: +3
M>Строки из STL практически нигде не используются. Используются велосипеды или char*. Ни с тем ни с другим std::string нормально не сопрягается. Главным образом потому, что c_str() возвращает не внутренний буфер, а временный. Лишнее копирование никому не нужно.


Doc>Re: Подводные камни &mdash; strcat и c_str()
Автор: Roman Odaisky
Дата: 16.08.06


Doc>

std::string::c_str() возвращает указатель типа char const *, содержащий size() + 1 символов, представляющих строку и завершающихся '\0'.
Указатель действителен до ближайшего вызова non-const метода.


Вот имменно.
Пример я привёл для того чтобы показать что в принципе c_str() и begin() могут указывать на одну и ту же
память.
Независимо от того, возвращает c_str() указатель на тот же буффер что и begin()
или нет, std::string ничего никуда не копирует при вызове c_str() c_str() вызывается за константное
время.
Кстати std::string ничего не копирует во "временный" буфер также при операциях вставки и добавлении,
я вас уверяю.

И это НЕ хороший тон, когда результат c_str() копируется куда-то ещё.
Нужно пользоваться тем что он валиден, до вызова неконстантной функции.

А я как минимум года 4 использую std::string, std::vector и не могу нарадоваться.
Вообще-то нужно ещё поискать классы, которые также хорошо и продуманно спроектированы
как std::string и std::vector

    std::string empty;//1

    std::string s("kolya petya vasya");//2
    s.c_str();//3
    s.append("supper pupper stroka");//4
    s.insert(s.size()/2,"supper pupper stroka");//5



1. Дефольтный конструктор не выделяет динамическую память
basic_string()
  : _Mybase()
{    // construct empty string
  _Tidy();
}

void _Tidy(bool _Built = false,
    size_type _Newsize = 0)
{    // initialize buffer, deallocating any storage
  if (!_Built);
  else if (_BUF_SIZE <= _Myres)
  {    // copy any leftovers to small buffer and deallocate
    _Elem *_Ptr = _Bx._Ptr;
    if (0 < _Newsize)
    _Traits::copy(_Bx._Buf, _Ptr, _Newsize);
        _Mybase::_Alval.deallocate(_Ptr, _Myres + 1);
  }
  _Myres = _BUF_SIZE - 1;
  _Eos(_Newsize);
}

void _Eos(size_type _Newsize)
{    // set new length and null terminator
    _Traits::assign(_Myptr()[_Mysize = _Newsize], _Elem());
}


2. Конструктор сводится к операции присваивания, а та в свою очередь
хранит данные сплошным массивом.
    basic_string(const _Elem *_Ptr)
        : _Mybase()
        {    // construct from [_Ptr, <null>)
        _Tidy();
        assign(_Ptr);
        }

    _Myt& assign(const _Elem *_Ptr)
        {    // assign [_Ptr, <null>)
        return (assign(_Ptr, _Traits::length(_Ptr)));
        }

    _Myt& assign(const _Elem *_Ptr, size_type _Num)
        {    // assign [_Ptr, _Ptr + _Num)
        if (_Inside(_Ptr))
            return (assign(*this, _Ptr - _Myptr(), _Num));    // substring

        if (_Grow(_Num))
            {    // make room and assign new stuff
            _Traits::copy(_Myptr(), _Ptr, _Num);
            _Eos(_Num);
            }
        return (*this);
        }



3. c_str() ничего не копирует во временный буффер, а просто возвращает указатель на буффер.
    const _Elem *c_str() const
        {    // return pointer to null-terminated nonmutable array
        return (_Myptr());
        }

    const _Elem *_Myptr() const
        {    // determine current pointer to buffer for nonmutable string
        return (_BUF_SIZE <= _Myres ? _Bx._Ptr : _Bx._Buf);
        }

В случае с vc7.1 приминяется оптимизация на маленьких строках оттуда и берёться _Bx._Buf
Собственно без этой оптимизации наверное и будет единственный случай когда c_str()!=&*begin()
std::string s;
s.c_str()//нету внутреннего буффера, поэтому &*begin()==0, а c_str() возвращает ""



4. Также все данные находяться в непрерывном массиве. Только увеличиваем память если нужно _Grow()
и копируем в конец
    _Myt& append(const _Elem *_Ptr)
        {    // append [_Ptr, <null>)
        return (append(_Ptr, _Traits::length(_Ptr)));
        }


    _Myt& append(const _Elem *_Ptr, size_type _Count)
        {    // append [_Ptr, _Ptr + _Count)
        if (_Inside(_Ptr))
            return (append(*this, _Ptr - _Myptr(), _Count));    // substring
        if (npos - _Mysize <= _Count)
            _String_base::_Xlen();    // result too long

        size_type _Num;
        if (0 < _Count && _Grow(_Num = _Mysize + _Count))
            {    // make room and append new stuff
            _Traits::copy(_Myptr() + _Mysize, _Ptr, _Count);
            _Eos(_Num);
            }
        return (*this);
        }




5. Также всё сплошным буффером, Увеличиваем, раздвигаем, копируем.

    _Myt& insert(size_type _Off, const _Elem *_Ptr)
        {    // insert [_Ptr, <null>) at _Off
        return (insert(_Off, _Ptr, _Traits::length(_Ptr)));
        }

    _Myt& insert(size_type _Off,
        const _Elem *_Ptr, size_type _Count)
        {    // insert [_Ptr, _Ptr + _Count) at _Off
        if (_Inside(_Ptr))
            return (insert(_Off, *this,
                _Ptr - _Myptr(), _Count));    // substring
        if (_Mysize < _Off)
            _String_base::_Xran();    // _Off off end
        if (npos - _Mysize <= _Count)
            _String_base::_Xlen();    // result too long
        size_type _Num;
        if (0 < _Count && _Grow(_Num = _Mysize + _Count))
            {    // make room and insert new stuff
            _Traits::move(_Myptr() + _Off + _Count,
                _Myptr() + _Off, _Mysize - _Off);    // empty out hole
            _Traits::copy(_Myptr() + _Off, _Ptr, _Count);    // fill hole
            _Eos(_Num);
            }
        return (*this);
        }



К сожалению у меня нет стандарта, и я не могу точно на него сослаться.
Но даже, если стандарт не запрещает, это не значит что реализация будет так делать.
Просто не зачем это делать

Ещё долго можно распинаться на тему того, как стоит использовать std::string, но наверное хватит

P.S. А вообще кто-нибудь видел вживую реализацию std::string и std::vector которые хранили бы данные не сплошным массивом?
Откуда такие мысли?
Re[6]: std::string::c_str(): потенциальное копирование (было: минусы STL)
От: Mazay Россия  
Дата: 23.08.06 17:11
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Mazay wrote:

>> A> some.SetText(text.c_str());
>> A>
>> с ещё одним копированием
C>Нет тут копирования во всех реализациях STL которые я знаю. С чего оно
C>должно появится?

А если внутренний буфер не одним куском выделен? Doc выше написал что выделенный буфер может умереть. Так что надо сразу копировать строку в "вечный" буфер.
Главное гармония ...
Re[4]: std::string::c_str(): потенциальное копирование (было: минусы STL)
От: kan_izh Великобритания  
Дата: 23.08.06 18:07
Оценка:
Шебеко Евгений wrote:

> Вот имменно.

> Пример я привёл для того чтобы показать что в принципе c_str() и begin()
> могут указывать на одну и ту же
> память.
> Независимо от того, возвращает c_str() указатель на тот же буффер что и
> begin()
> или нет, std::string ничего никуда не копирует при вызове c_str()
> c_str() вызывается за константное
> время.
Это в стандарте не обещано, а если на это полагаться, то получится implementation specific, т.е. поменяв версию stl на
что-нибудь другое, поведение может изменится и c_str будет создавать временную копию (например, если строка хранится по
кусочкам, или используется пул строк).

> Кстати std::string ничего не копирует во "временный" буфер также при

> операциях вставки и добавлении,
> я вас уверяю.

> И это НЕ хороший тон, когда результат c_str() копируется куда-то ещё.

> Нужно пользоваться тем что он валиден, до вызова неконстантной функции.
Это да. На самом деле c_str() сделан лишь для совместимости с С-style строками, и им пользоваться нужно по минимуму.
Posted via RSDN NNTP Server 2.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.