Re[5]: Заполняем vector<vector<string> >
От: IROV..  
Дата: 12.08.09 10:10
Оценка:
Здравствуйте, igna, Вы писали:

I>Это правило возможно устарело. VC++, GCC и Intel C++ поддерживают RVO: http://en.wikipedia.org/wiki/Return_value_optimization


IRO>>З.Ы. не использовать шаблоные типы напрямую (заменить на typedef)


I>Так. А это почему?


http://www.rsdn.ru/forum/cpp/3501461.1.aspx
Автор: IROV..
Дата: 12.08.09


Это правило хорошего тона распостраняется на контейнеры у которых есть скрытый кэш.

да RVO порезало это правило, например std::list теперь так немного безсмыслено передавать. (Но например мне не впадло передать по ссылке, и душа не болит)

я не волшебник, я только учусь!
Re: Заполняем пользовательский тип
От: igna Россия  
Дата: 12.08.09 10:17
Оценка:
Или как вариант вместо vector<vector<string> > пользовательский тип:

struct my_sentence : vector<string> {
    my_sentence(Sentence const* const sent)
    {
        for (Word const* w = sent->FirstWord(); w; w = w->Next())
            push_back(w->Str()); // w->Str() returns char const*
    }
};

struct my_text : vector<my_sentence> {
    my_text(Text const* const text)
    {
        for (Sentence const* sent = text->FirstSentence(); sent; sent = sent->Next())
            push_back(my_sentence(sent));
    }
};


Вопрос тот же, как бы вы написали в этом случае (при условии, что необходимость оптимизации данного места в программе не выявлена)?
Re[2]: Заполняем пользовательский тип
От: IROV..  
Дата: 12.08.09 10:21
Оценка:
Здравствуйте, igna, Вы писали:

I>Или как вариант вместо vector<vector<string> > пользовательский тип:


I>
I>struct my_sentence : vector<string> {
I>    my_sentence(Sentence const* const sent)
I>    {
I>        for (Word const* w = sent->FirstWord(); w; w = w->Next())
I>            push_back(w->Str()); // w->Str() returns char const*
I>    }
I>};

I>struct my_text : vector<my_sentence> {
I>    my_text(Text const* const text)
I>    {
I>        for (Sentence const* sent = text->FirstSentence(); sent; sent = sent->Next())
I>            push_back(my_sentence(sent));
I>    }
I>};
I>


I>Вопрос тот же, как бы вы написали в этом случае (при условии, что необходимость оптимизации данного места в программе не выявлена)?


Не люблю процесинг в конструкторах

надо конвертнуть Text в my_text -> функция.

я не думаю что my_text и Text это такие базовые вещи для которых это очевидное преобразование.

Text tx;

...

my_text mt( tx );


я не волшебник, я только учусь!
Re[4]: Заполняем vector<vector<string> >
От: igna Россия  
Дата: 12.08.09 10:26
Оценка:
Здравствуйте, IROV.., Вы писали:

IRO>+ Разьясню, вектор который мы туда передадим может уже быть за ресайзеный(выделено памяти) и тогда внутрения функция ресайз (в тру версии) не будет ничего делать а проскипается, вот эту оптимизацию компилятор в твоем случаее не сделает.


Можно конкретный пример? Не обязательно для приведенного мной случая, а какой-нибудь самый простенький, где "заресайзеный" и "проскипается", и чтобы компилятор оптимизацию не сделал.
Re[4]: Заполняем vector<vector<string> >
От: Alexander G Украина  
Дата: 12.08.09 10:30
Оценка:
AG>С оптимизацией — оборачиваю потенциально большие контейнеры в shared_ptr, но и в этом случае push_back нулевого указателя дешевле ненулевого.

А когда будет emplace_back, выгода от вставки пустого и использования back будет ещё больше:

vector<vector<string> > text_to_vvs(Text const* const text)
{
  vector<vector<string> > vvs;
  for (Sentence const* sent = text->FirstSentence(); sent; sent = sent->Next()) {
    vvs.emplace_back();
    vector<string> & vs = vvs.back();
    for (Word const* w = sent->FirstWord(); w; w = w->Next())
      vs.emplace_back(w->Str()); // w->Str() returns char const*
  }
  return vvs;
}
Русский военный корабль идёт ко дну!
Re[3]: Заполняем пользовательский тип
От: igna Россия  
Дата: 12.08.09 10:36
Оценка:
Здравствуйте, IROV.., Вы писали:

IRO>Не люблю процесинг в конструкторах


А я люблю неизменяемые объекты и использую их везде, где только можно.
Re[2]: Заполняем пользовательский тип
От: igna Россия  
Дата: 12.08.09 10:43
Оценка:
I>Или как вариант вместо vector<vector<string> > пользовательский тип:

И тогда определив соответствующие итераторы можно написать так:

struct my_sentence : vector<string> {
    my_sentence(Sentence const* const sent)
        : vector<string>(word_iterator(sent), word_iterator()) {}
};

struct my_text : vector<my_sentence> {
    my_text(Text const* const text)
        : vector<my_sentence>(sentence_iterator(text), sentence_iterator()) {}
};
Re: Заполняем vector<vector<string> >
От: zaufi Земля  
Дата: 12.08.09 12:01
Оценка: 1 (1)
Здравствуйте, igna, Вы писали:

I>Пример реализован прямолинейно, а как бы вы написали?

не знаю что такое Text в твоей проге, но если гдето там (в коде до указанного примера) есть буфер (char* или std::string например) с текстом над которым нужно произвести данные зверства...

0) я бы сначла нарезал его boost::algorithm::split'ом на предложения (например по символу '.' в тексте), результат получил бы в std::vector<boost::iterator_range<char*> > или std::vector<boost::iterator_range<std::string::const_iterator> > (не знаю в чем у тя хрянятся строки)

1) потом проходясь по вектору range'й резал бы по словам, опять таки split'ом в вектор range'й и полученые вектора складывал бы в вектор векторов буст итератор рэнджей от констных стринговых итераторов

не знаю уж зачем тебе такое надо... -- не иначе словарь составляешь для брутфорсового подбора паролей

в результате не буит никаких копирований строк вообще... ну и размер внешнего вектора тоже буит известен после шага 0
Re[3]: Заполняем vector<vector<string> >
От: Аноним  
Дата: 12.08.09 12:28
Оценка:
Здравствуйте, igna, Вы писали:

I>Здравствуйте, Аноним, Вы писали:


I>
I>    return count;
I>


I>Зачем count?

А вдруг понадобится узнать сколько все таки элементов скопировалось? Тем более что в функцию можно
передать vvs уже частично заполненый.
Вообще стараюсь, чтобы функция которая копирует данные из объекта одного типа в объект имееющий другой тип что то возвращала.
Почти всегда это было нужно.
Re[2]: Заполняем vector<vector<string> >
От: igna Россия  
Дата: 12.08.09 13:18
Оценка:
Здравствуйте, zaufi, Вы писали:

Z>не знаю что такое Text в твоей проге, но если гдето там (в коде до указанного примера) есть буфер (char* или std::string например) с текстом над которым нужно произвести данные зверства...


Нет буфера. Остальное зря писал, значит.
Re[2]: Заполняем vector<vector<string> >
От: SleepyDrago Украина  
Дата: 12.08.09 13:50
Оценка: 1 (1)
Здравствуйте, zaufi, Вы писали:

полностью с вами согласен — правда можно чуток поковырять детали

I>>Пример реализован прямолинейно, а как бы вы написали?

Z>не знаю что такое Text в твоей проге, но если гдето там (в коде до указанного примера) есть буфер (char* или std::string например) с текстом над которым нужно произвести данные зверства...

Z>0) я бы сначла нарезал его boost::algorithm::split'ом на предложения (например по символу '.' в тексте), результат получил бы в std::vector<boost::iterator_range<char*> > или std::vector<boost::iterator_range<std::string::const_iterator> > (не знаю в чем у тя хрянятся строки)


Если разделители фиксированного размера, то рулит хранение позиций начала предложений. Экономия памяти на 64х битной платформе в типовом случае в 4 раза (разумеется при известных ограничениях). Так что вы несомненно правы, а предлагается лишь небольшое влияние на константы алгоритма.

Z>1) потом проходясь по вектору range'й резал бы по словам, опять таки split'ом в вектор range'й и полученые вектора складывал бы в вектор векторов буст итератор рэнджей от констных стринговых итераторов

вектор векторов можно скипнуть совсем — достаточно 2 вектора : вектор слов + на каждое предложение индекс начала. Причем вектор наверное стоит заменить на что-то блочное (упражнения для читателя).

Z>не знаю уж зачем тебе такое надо... -- не иначе словарь составляешь для брутфорсового подбора паролей

Он известный ценитель этого форума так что код скорее всего измеряет чью-то скорость.

Z>в результате не будет никаких копирований строк вообще... ну и размер внешнего вектора тоже буит известен после шага 0

В общем то все верно для generic case. Но на практике часто можно воспользоваться тем, что данные ограничены по длине.
Re[2]: Заполняем vector<vector<string> >
От: igna Россия  
Дата: 12.08.09 14:13
Оценка:
Здравствуйте, zaufi, Вы писали:

Z>0) я бы сначла нарезал его boost::algorithm::split'ом на предложения (например по символу '.' в тексте),...


Кстати, предложение может заканчиваться вопросительным или восклицательным знаком. Кроме того оно может окачиваться троеточием, которое не должно приводить к появлению двух пустых предложений. Пустых предложений вообще не должно быть, таким образом двоеточие не являющееся началом троеточия должно приводить к ошибке и выводу соответствующего сообщения. Затем точка внутри кавычек не является концом предложения, причем кавычки могут быть одинарные, двойные и другие определенные в UNICODE. Точка после цифры в начале предложения не является признаком его конца и так далее...

Все-таки не всегда стоит писать свой парсер.
Re: Заполняем vector<vector<string> >
От: Шахтер Интернет  
Дата: 12.08.09 14:20
Оценка: 1 (1) -2
Здравствуйте, igna, Вы писали:

I>Пример внизу заполняет vector<vector<string> > беря значения из некой коллекции:


I>Пример реализован прямолинейно, а как бы вы написали?


Я бы уволил с работы человека, использующего такие конструкции.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[2]: Заполняем vector<vector<string> >
От: igna Россия  
Дата: 12.08.09 14:39
Оценка:
Здравствуйте, Шахтер, Вы писали:

Ш>Я бы уволил с работы человека, использующего такие конструкции.


Что за воинствующее мракобесие?

С.7 Multidimensional Arrays

It is not uncommon to need a vector of vectros, a vector of vector of vectors, etc. ...

(The C++ Programming Language, Third Edition, Bjarne Stroustrup)

Re[5]: Заполняем vector<vector<string> >
От: IROV..  
Дата: 12.08.09 14:59
Оценка:
Здравствуйте, igna, Вы писали:

I>Здравствуйте, IROV.., Вы писали:


IRO>>+ Разьясню, вектор который мы туда передадим может уже быть за ресайзеный(выделено памяти) и тогда внутрения функция ресайз (в тру версии) не будет ничего делать а проскипается, вот эту оптимизацию компилятор в твоем случаее не сделает.


I>Можно конкретный пример? Не обязательно для приведенного мной случая, а какой-нибудь самый простенький, где "заресайзеный" и "проскипается", и чтобы компилятор оптимизацию не сделал.


typedef std::list<std::string> TListFlags;
typedef std::vector<std::string> TVectorFlags;

static void converterListToVectorFlags( const TListFlags & _in, TVectorFlags & _out )
{
    //...
}

class Properties
{
public:
    void addFlags( const TListFlags & _list )
    {
        converterListToVectorFlags( _list, m_flags );
    }

protected:    
    TVectorFlags m_flags;
};


я не волшебник, я только учусь!
Re[6]: Заполняем vector<vector<string> >
От: igna Россия  
Дата: 12.08.09 15:12
Оценка:
Здравствуйте, IROV.., Вы писали:

IRO>typedef std::list<std::string> TListFlags;
IRO>typedef std::vector<std::string> TVectorFlags;

IRO>static void converterListToVectorFlags( const TListFlags & _in, TVectorFlags & _out )
IRO>{
IRO>    //...
IRO>}

IRO>class Properties
IRO>{
IRO>public:
IRO>    void addFlags( const TListFlags & _list )
IRO>    {
IRO>        converterListToVectorFlags( _list, m_flags );
IRO>    }

IRO>protected:    
IRO>    TVectorFlags m_flags;
IRO>};


Прошу прощения, похоже я недостаточно точно выразился. Под конкретным примером имел в виду код, который можно скомпилировать, запустить и посмотреть, как компилятор не соптимизирует возврат по значению.
Re[7]: Заполняем vector<vector<string> >
От: IROV..  
Дата: 12.08.09 15:17
Оценка: 4 (1)
I>Прошу прощения, похоже я недостаточно точно выразился. Под конкретным примером имел в виду код, который можно скомпилировать, запустить и посмотреть, как компилятор не соптимизирует возврат по значению.


#    include <vector>
#    include <list>
#    include <string>

typedef std::list<std::string> TListFlags;
typedef std::vector<std::string> TVectorFlags;

static void s_converterListToVectorFlags( const TListFlags & _in, TVectorFlags & _out )
{
    for( TListFlags::const_iterator 
        it = _in.begin(),
        it_end = _in.end();
    it != it_end;
    ++it )
    {
        _out.push_back( *it );
    }
}

static TVectorFlags s_converterListToVectorFlags2( const TListFlags & _in )
{
    TVectorFlags out;

    for( TListFlags::const_iterator 
        it = _in.begin(),
        it_end = _in.end();
    it != it_end;
    ++it )
    {
        out.push_back( *it );
    }

    return out;
}


class Properties
{
public:
    void setFlags( const TListFlags & _list )
    {
        m_flags.clear();
        s_converterListToVectorFlags( _list, m_flags );

        //    m_flags = s_converterListToVectorFlags2( _list )
    }

protected:    
    TVectorFlags m_flags;
};

void main()
{
    Properties pr;

    TListFlags ff;
    ff.push_back( "const" );
    ff.push_back( "copy" );
    ff.push_back( "alpha" );

    pr.setFlags( ff );

    TListFlags gg;
    gg.push_back( "write" );
    gg.push_back( "read" );
    gg.push_back( "float" );

    pr.setFlags( gg );
}
я не волшебник, я только учусь!
Re[3]: Заполняем vector<vector<string> >
От: Шахтер Интернет  
Дата: 12.08.09 17:05
Оценка:
Здравствуйте, igna, Вы писали:

I>Здравствуйте, Шахтер, Вы писали:


Ш>>Я бы уволил с работы человека, использующего такие конструкции.


I>Что за воинствующее мракобесие?


Это не воинствующее мракобесие, а твой воинствующий дилетантизм.

I>

I>С.7 Multidimensional Arrays

I>It is not uncommon to need a vector of vectros, a vector of vector of vectors, etc. ...

I>(The C++ Programming Language, Third Edition, Bjarne Stroustrup)


stl::vector для решения этой задачи не подходит категорически. Потому что в него нельзя складывать объекты с тяжелым оператором копирования -- слишком накладно получается. А использовать дешевые move/swap он не позволяет по дизайну. А здесь два уровня -- исключительно неэффективное решение.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[4]: Заполняем vector<vector<string> >
От: SleepyDrago Украина  
Дата: 12.08.09 20:18
Оценка:
Здравствуйте, Шахтер, Вы писали:

Ш>stl::vector для решения этой задачи не подходит категорически. Потому что в него нельзя складывать объекты с тяжелым оператором копирования -- слишком накладно получается. А использовать дешевые move/swap он не позволяет по дизайну. А здесь два уровня -- исключительно неэффективное решение.

Самое смешное что rvalue references в VS2010 ускоряют этот ужас раз в 20. И такой код будет и дальше применяться не смотря на массовые расстрелы Недавно на блоге студии был пример ускорения как раз vector<vector<string>>
Re[4]: Заполняем vector<vector<string> >
От: igna Россия  
Дата: 13.08.09 04:04
Оценка:
Здравствуйте, Шахтер, Вы писали:

Ш>stl::vector для решения этой задачи не подходит категорически. Потому что в него нельзя складывать объекты с тяжелым оператором копирования -- слишком накладно получается. А использовать дешевые move/swap он не позволяет по дизайну. А здесь два уровня -- исключительно неэффективное решение.


Ты бы все же посмотрел пример vector of vectors у Страуструпа. Можешь еще примечание на полях сделать, мол автор есть дилетант и предлагаемое им решение неэффективно.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.