Почему строки VC ++ не учитываются? - PullRequest
13 голосов
/ 01 апреля 2009

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

Простой тест показывает семантику копирования при записи:

#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 и получил похожие результаты - строки работают как контейнеры для копирования при записи.

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

Почему?

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

Спасибо

Ответы [ 5 ]

22 голосов
/ 01 апреля 2009

Я думаю, что все больше и больше std::string реализаций отойдут от пересчета / копирования при записи, поскольку это часто встречная оптимизация в многопоточном коде.

См. Статью Херба Саттера Оптимизации, которых нет (в многопоточном мире) .

11 голосов
/ 01 апреля 2009

Фактическая STL требует, чтобы при использовании подсчета ссылок семантика была такой же, как и для версии без подсчета ссылок. Это не тривиально для общего случая. (Вот почему вы не должны писать свой класс on 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

7 голосов
/ 02 апреля 2009

Как заявили Martin & Michael, Copy On Write (COW) часто доставляет больше хлопот, чем стоит, для дальнейшего чтения посмотрите эту превосходную статью Kelvin Henney о Mad COW Disease и я считаю, что Андрей Александреску заявил, что Small String Optimization работает лучше во многих приложениях (но я не могу найти статью).

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

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 
    }
    // ...
};
5 голосов
/ 01 апреля 2009

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

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

1 голос
/ 01 апреля 2009

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

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

...