Подтвердить что ты не робот

Почему строки VС++ не подсчитываются?

Стандарт STL не требует от std::string для пересчета. Но на самом деле большинство С++ реализации предоставляют обновленные, скопированные строки, позволяющие вам проходить строка по значению как примитивный тип. Также эти реализации (по крайней мере, g++) используют атомных операций, делающих эти строки незакрепленными и безопасными по потоку.

Простой тест показывает семантику copy-on-write:

#include <iostream>
#include <string>

using namespace std;

void foo(string s)
{
    cout<<(void*)s.c_str()<<endl;
    string ss=s;
    cout<<(void*)ss.c_str()<<endl;
    char p=ss[0];
    cout<<(void*)ss.c_str()<<endl;
}

int main()
{
    string s="coocko";
    cout<<(void*)s.c_str()<<endl;
    foo(s);
    cout<<(void*)s.c_str()<<endl;
}

Только два адреса печатаются точно после использования непостоянного члена.

Я протестировал этот код с помощью компилятора HP, GCC и Intel и получил аналогичные результаты - строки работать как контейнеры для копирования на запись.

С другой стороны, VС++ 2005 ясно показывает, что каждая строка полностью скопирована.

Почему?

Я знаю, что в VС++ 6.0 произошла ошибка, у которой была небезобезопасная реализация подсчет ссылок, вызвавший случайные программные судороги. Это причина? Они просто боятся использовать ref-counting больше, даже это обычная практика? Они предпочитают не использовать ref-counting для решения проблемы?

Спасибо

4b9b3361

Ответ 2

Действительный STL требует, чтобы, если вы используете подсчет ссылок, семантика будет такой же, как для подсчитываемой версии без ссылки. Это не является тривиальным для общего случая. (Вот почему вы не должны писать свой класс string).

Из-за следующей ситуации:

std::string   x("This is a string");
char&         x5 = x[5];
std::string   y(x);

x5 = '*';

Подробнее см. http://www.sgi.com/tech/stl/string_discussion.html

Ответ 3

Как сказано Мартином и Майклом, Copy On Write (COW) часто больше проблем, чем того стоит, для дальнейшего чтения см. эту замечательную статью Келвина Хенни о Mad COW Disease, и я считаю, что Андрей Александреску заявил, что Оптимизация небольших строк работает лучше во многих приложениях (но я не могу найти статью).

Оптимизация небольших строк - это то, где вы делаете строковый объект больше и избегаете выделения кучи для небольших строк. Реализация игрушек будет выглядеть примерно так:

class string {
    char *begin_, *end_, *capacity_;
    char buff_[64]; // pick optimal size (or template argument)
public:
    string(const char* str)
    {
        size_t len = strlen(str);
        if (len < sizeof(buff_))
        {
            strcpy(buff_, str);
            begin_ = buff_;
            capacity_ = buff_ + sizeof(buff_);
        }
        else
        {
            begin_ = strdup(str);
            capacity_ = begin_ + len;
        }
        end_ = begin_+len;
    }

    ~string()
    {
        if (begin_ != buff_)
            free(begin_); // strdup requires free 
    }
    // ...
};

Ответ 4

Возможно, Microsoft определила, что копирование строк не является большой проблемой, так как почти все С++-коды используются, когда это возможно, по ссылке. Поддержание контрольного счета имеет накладные расходы в пространстве и времени (без учета блокировки), которые, по их мнению, не стоили платить.

Или, может быть, нет. Если это вас беспокоит, вы должны профилировать свое приложение, чтобы определить, является ли строковое копирование основной накладной, и если оно переключается на другую реализацию строки.

Ответ 5

Это не главная причина, но я видел много неправильного кода под платформой win32, которые делают что-то вроде const_cast< char* >( str.c_str() ).

Возможно, Microsoft знает об этом и заботится о разработчиках:)