Перейти из форума на сайт.

НовостиФайловые архивы
ПоискАктивные темыТоп лист
ПравилаКто в on-line?
Вход Забыли пароль? Первый раз на этом сайте? Регистрация
Компьютерный форум Ru.Board » Компьютеры » Прикладное программирование » Вопросы по программированию на C/С++

Модерирует : ShIvADeSt

 Версия для печати • ПодписатьсяДобавить в закладки
Страницы: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322

Открыть новую тему     Написать ответ в эту тему

Crazy_Shrike



Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
Вопросы по программированию на C/С++

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

    Решения конкретных задач собираются и обсуждаются в теме Задачи по C/С++ .

    Прежде чем просить помощи в задании...
    Если позарез надо и вы даже готовы заплатить

    Как правильно задавать вопросы, если вы хотите получить ответ.

    Полезные ссылки:
    C++(eng)

  • Всего записей: 241 | Зарегистр. 25-03-2004 | Отправлено: 13:37 06-05-2004 | Исправлено: AZJIO, 19:45 12-05-2014
    Abs62



    Gold Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    distance

    Цитата:
    Согласно стандарту, передача NULL в функцию освобождения памяти (free) безопасна.

    Насколько я помню, это относится к operator delete, но никак не к free().

    Всего записей: 6080 | Зарегистр. 22-10-2005 | Отправлено: 00:30 28-01-2007
    xdude



    Full Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    distance

    Цитата:
    Согласно стандарту, передача NULL в функцию освобождения памяти (free) безопасна.

    Дык я в предыдущих постах писал: там не только free, там разные функции юзаются, и ресурсы разные: от char *buf до HMODULE и HRESOURCE. В принципе, вариант с while, наверное, самый удобный. В любом случае, даже если auto_ptr использовать - всё равно будут лишний раз проверка на NULL делаться, только уже в деструкторе auto_ptr.
    Qraizer

    Цитата:
    И правильно делает, что не пропускает.

    Так значит иначе как через вспомогательную функцию никак нельзя? Тогда другой вопрос: есть класс

    Код:
     
    file "c.h":
    class C
    {
    ...
    protected:
      virtual void* Callback();
    ...
    };
     
    file "c.cpp":
    static void *__callback(void* ptr)
    {
      ((C)ptr)->Callback();
    };
     

    Естественно, такая конструкция не работает, так как метод Callback является protected. А как можно статическиу функцию объявить как friend? Я пробовал - не получается. Это что, надо либо функцию делать нестатической, либо метод объявлять как public? Другого выхода нет?

    Всего записей: 481 | Зарегистр. 04-11-2004 | Отправлено: 00:40 28-01-2007
    distance

    Advanced Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Abs62
    и для free тоже
    ... If ptr is a null pointer, no action occurs ...
    xdude

    Цитата:
    там не только free, там разные функции юзаются, и ресурсы разные

    либо для каждого ресурса создать свой handle-класс (возможно темплейтный policy-based, возможно применение готового), либо, как уже упоминалось, для boost::shared_ptr можно указать custom deleter, либо просто аккуратно программировать
     

    Цитата:
    Тогда другой вопрос: есть класс  

    ты бы описал конечную цель: что требуется в итоге получить? а то все эти кастинги как-то странновато выглядят...

    Всего записей: 878 | Зарегистр. 28-03-2004 | Отправлено: 01:07 28-01-2007
    xdude



    Full Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    distance

    Цитата:
    ты бы описал конечную цель: что требуется в итоге получить?

    Вот это:

    Цитата:
    Есть функция:  
    typedef void* (*callback_t) (void*);  
    int somefunc(int flags, callback_t callback,void* callback_param);  
    и есть класс Someclass  
    {  
    ...  
    virtual void *somemethod();  
    };  
     
    Есть ли возможность передать указатель метод Someclass::somemethod в функцию somefunc? somefunc(flags,(callback_t)this->somemethod,this) не срабатывает, другое всё тоже перепробовал. Пришлось создать вспомогательную функцию, которой передается указатель на объект класса, и которая вызывает ((Someclass*)ptr)->somemethod();  
    А напрямую никак нельзя?  

    Выяснили, что напрямую нельзя, т.е., я создал вспомогательную функцию, которая и вызывает необходимый метод класса. проблема в том, что этот метод объявлен как protected. А вспомогательную функцию я сделал static (зачем она где-то ещё нужна, если я её только в одном месте использую). Так вот вопрос: как из static-функции получить доступ к protected-методу класса (static-функция не является методом этого класса, но описана в том же cpp файле, где имплементируются все остальные методы класса)? Объявить её как friend я попробовал - не вышло.
     
    Добавлено:
    Если быть более конкретным - то в данном случае мне нужно виртуальный метод Main() класса CThread  передать как параметр в API-функцию pthread_create (или виндовую CreateThread), но на самом деле это не имеет значения, т.к. в общем случае функция и класс могут называться как угодно, мне интересен сам подход.

    Всего записей: 481 | Зарегистр. 04-11-2004 | Отправлено: 01:31 28-01-2007
    distance

    Advanced Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    xdude
    у тебя изначально неверный подход к проблеме.
    поскольку впрямую языковыми средствами задача не решаема, ты пытаешься приделать какие-то костыли в виде статических функций etc, тогда как подлежит пересмотру сама концепция.
     
    напрмер, вместо примитивного указателя на функцию можно использовать boost::function

    Код:
    typedef boost::function<void (void* param)> callback_t;
     
    int somefunc(int flags, callback_t callback,void* callback_param);

     
    Всё.
    Этим кодом ты избавляешься от жесткой призязки твоего callback'а к сигнатуре метода.
    С помощью Boost.Bind ты можень "привязвать" к этому callback'у как вызов обычной функции, как и вызов функции-члена класса.

    Всего записей: 878 | Зарегистр. 28-03-2004 | Отправлено: 01:44 28-01-2007
    Abs62



    Gold Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    distance

    Цитата:
    и для free тоже  
    ... If ptr is a null pointer, no action occurs ...  

    Значит, это мои давние воспоминания.
     
    xdude

    Цитата:
    Так вот вопрос: как из static-функции получить доступ к protected-методу класса (static-функция не является методом этого класса, но описана в том же cpp файле, где имплементируются все остальные методы класса)? Объявить её как friend я попробовал - не вышло.

    А объявить её статическим методом класса пробовал?

    Всего записей: 6080 | Зарегистр. 22-10-2005 | Отправлено: 01:54 28-01-2007
    xdude



    Full Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    distance
    Я не использую boost. И не хочу. Мне вполне хватает STL. Иначе бы я не парился со своим классом CThread, а взял бы бустовский Boost.Thread.
     
    Добавлено:

    Цитата:
    А объявить её статическим методом класса пробовал?

    А она пройдёт при этом в API-функцию по тайп-касту? Надо будет попробовать.

    Всего записей: 481 | Зарегистр. 04-11-2004 | Отправлено: 01:57 28-01-2007
    xdude



    Full Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Друзья, а есть в STL какая-то функция, которая разбила бы данные в строке, разделенные запятыми (или пробелами, или очередностью символов) на вектор (или список) строк? Типа "test1, test2, test3, test4" на вектор из 4-х строк: "test1", "test2", "test3" и "test4"?
    boost не предлагать

    Всего записей: 481 | Зарегистр. 04-11-2004 | Отправлено: 04:59 28-01-2007
    Green2454332

    Newbie
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Народ 1 вопрос не каво канкретно идти учится чтоб стать програмистом и понемать вас???

    Всего записей: 1 | Зарегистр. 29-01-2007 | Отправлено: 04:00 29-01-2007
    xdude



    Full Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Green2454332
    Если чиста канкретна то лучшы школу сначала закончеть и выучить русский изык чтоб тибя понемали, а уже патом изучать изыки праграмиравания.

    Всего записей: 481 | Зарегистр. 04-11-2004 | Отправлено: 04:08 29-01-2007
    xdude



    Full Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Товарищи, что-то втыкнуть никак не могу, мозги уже закипают: как написать универсальный темплейт класса, который будет в своём деструкторе освобождать переменную требуемого типа требуемой функцией? Например, есть MYSQL_RES* ptr, и есть функция mysql_free_result(MYSQL_RES *result), или метод класса-враппера CMysql::FreeResult(MYSQL_RES* res). Что с этим делать?
     
    Добавлено:
    Qraizer aka Boroda
    По твоему совету взял функцию отсюда:
    http://forums.realcoding.net/index.php?s=44184a4106fb132e44572b4597d2a3d3&showtopic=15556&st=15
    Заменил там только basic_string<Ch> на string, вызываю:

    Код:
     
    char *buf;
    ...
    unsigned int id=from_string<unsigned int>(buf);
     

    Компилируется нормально, во время исполнения выкидывает эксепшн St8bad_cast.
    Если вызвать from_string<int> - вообще ругается при компиляции почему-то (типа, нет подходящего прототипа для вызова ...get(...), и перечисляет все возможные прототипы, с unsigned int в том числе).
    Использую MinGW/GCC (G++) последней версии.
    Выручай
     
    Добавлено:
    cerr << buf при этом выдаёт число, например, 7 или 8 (что неважно).

    Всего записей: 481 | Зарегистр. 04-11-2004 | Отправлено: 06:34 29-01-2007
    Mickey_from_nsk

    Advanced Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    xdude

    Цитата:
    Товарищи, что-то втыкнуть никак не могу, мозги уже закипают: как написать универсальный темплейт класса, который будет в своём деструкторе освобождать переменную требуемого типа требуемой функцией?

    Насколько я помню, это делается объявлением стратегий при создании класса-освободителя. Или явными спецификациями шаблона.

    Всего записей: 636 | Зарегистр. 21-10-2002 | Отправлено: 08:28 29-01-2007
    xdude



    Full Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Mickey_from_nsk

    Цитата:
    Насколько я помню, это делается объявлением стратегий при создании класса-освободителя. Или явными спецификациями шаблона.

    Отсюда поподробней, пожалуйста

    Всего записей: 481 | Зарегистр. 04-11-2004 | Отправлено: 08:46 29-01-2007
    Mickey_from_nsk

    Advanced Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору

    Цитата:
    Отсюда поподробней, пожалуйста  

    Честно говоря, в твоем примере я не совсем понял постановку задачи. Там есть один объект? Какого типа этот объект? Приведенные тобой функция и метод делают одно и то же? Зачем приведены оба?
     
    По поводу стратегий - создается сец. класс, напр., FreingStrategy с методом freeObject.
    Потом от него наследуются стратегии FunctionFreingStrategy, в которой освобождение объекта в методе freeObject идет через вызов функции и MethodFreingStrategy - там - через вызов метода.
    Класс освободитель кроме отслеживаемого объекта принимает еще и указатель на стратегию освобождения. В своем деструкторе просто вызывает метод freeObject для данной стратегии.
     

    Всего записей: 636 | Зарегистр. 21-10-2002 | Отправлено: 09:17 29-01-2007
    xdude



    Full Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору

    Цитата:
    Зачем приведены оба?

    Да, и функция и метод делают одно и то же, привел ради полноты картины: хочу выяснить, можно ли и в том и в том случае сделать универсальный темплейт высвобождателя.
    Насчет стратегии так и не понял: получается, что это не универсальный темплейт, а некий базовый класс, и для каждого нужного мне типа данных и функции-высвобождателя мне нужно писать для него класс-потомок, который будет реализовывать исполнение нужной функции высвобождения в каком-то своём методе (или в деструкторе)?

    Всего записей: 481 | Зарегистр. 04-11-2004 | Отправлено: 13:20 29-01-2007
    distance

    Advanced Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    xdude

    Цитата:
    Друзья, а есть в STL какая-то функция, которая разбила бы данные в строке, разделенные запятыми (или пробелами, или очередностью символов) на вектор (или список) строк? Типа "test1, test2, test3, test4" на вектор из 4-х строк: "test1", "test2", "test3" и "test4"?  

    тогда вручную, очевидно...
    Код:
     
    template <typename T>
    std::vector<std::basic_string<T> > split(std::basic_string<T>& s)
    {
        typedef std::basic_string<T> S;
        std::vector<S> v;
     
        std::basic_stringstream<T> str(s);
        std::copy(
            std::istream_iterator<S>(str),
            std::istream_iterator<S>(),
            std::back_inserter(v));
        return (v);
    }

     
    использование:

    Код:
    std::string s1 = ...;
        std::vector<std::string> v = split(s);

     
    PS. я сначала про запятые не заметил, так что вышеприведенный код запятые не распознает. Well... в конце-концов string::find никто не отменял
     

    Цитата:
    Я не использую boost. И не хочу

    Бустовский код был приведен только в качестве демонстрации парадигмы think different (c)
     

    Цитата:
    А она пройдёт при этом в API-функцию по тайп-касту? Надо будет попробовать.

    Посмотри, что ли, хотя бы как реализован тот же CWinThread из MFC, или куча аналогичных велосипедов на code project. Вкраце смысл таков: при создании потока, в качестве точки входа передается адрес статической функции этого класса, и this как lpParameter. А остальное - дело техники:

    Код:
    LRESULT CMyThread::ThreadWorker(LPVOID lpParameter)
    {
        CMyThread* pThis = reinterpret_cast<CMyThread*>(lpParameter);
     
        // вызывается виртуальная функция, которая перегружается потомком
        // и реализует свою custom-функциональность.
        return (pThis->Run());
    }


    Всего записей: 878 | Зарегистр. 28-03-2004 | Отправлено: 15:02 29-01-2007 | Исправлено: distance, 15:08 29-01-2007
    xdude



    Full Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    distance
    Всё время забываю спросить:

    Цитата:
    CMyThrread pThis = reinterpret_cast<CMyThread>(lpParameter);

    Все эти dynamic_cast, reinterpreter_cats и иже с ними - зачем они? Я с С на С++ перешёл, недоучил чего-то, наверное, не понимаю: почему нельзя тупо вот так написать:

    Цитата:
    CMyThrread *pThis = (CMyThread*)lpParameter;

     
     
    Добавлено:
    Только что посмотрел Бьерн Страуструп. Язык программирования С++. Там описывается только ptr_cast и ref_cast, reinterpret_cast я там не нашёл. Где можно обо всех этих кастах поподробнее почитать, желательно на русском?
     

    Всего записей: 481 | Зарегистр. 04-11-2004 | Отправлено: 15:17 29-01-2007
    distance

    Advanced Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    xdude
    Хм. ptr_cast у Страуструпа? Я должно быть что-то пропустил, этот оператор мне незнаком.

    Цитата:
     Все эти dynamic_cast, reinterpreter_cats и иже с ними - зачем они? Я с С на С++ перешёл, недоучил чего-то, наверное, не понимаю: почему нельзя тупо вот так написать:  

    можно и так. главное отличие "старого стиля" что он - один на все случаи, и потенциально небезопасен, а в с++ - есть четкая специализация. например:
     
    Foo* p = new Bar();
     
    Bar* b = (Bar*) p; // если p на самом деле не является потомком от Bar, то ...
    p->f(); // ... вот тут нас ждет большой сюрприз
     
    // а это безопасное приведение типов
    // в случае когда кастинг невозможен, dynamic_cast вернет NULL
    // хотя, imho, если в программе используется dynamic_cast, значит с архитектурой что-то не так...
    if (Bar* b = dynamic_cast<Bar*>(p))
    {
        p->f();
    }
     
    reinterpret_cast - это вариант близкий к сишному кастингу.

    Всего записей: 878 | Зарегистр. 28-03-2004 | Отправлено: 16:01 29-01-2007
    xdude



    Full Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    distance
    Ага, вроде понятно. А это стандарт языка, или чисто мелкосовтовская специфика?
     

    Цитата:
    ptr_cast у Страуструпа? Я должно быть что-то пропустил, этот оператор мне незнаком.

    Это даже не оператор. Он зачем-то описывает реализцию всего того, что делает dynamic_cast, с помощью функций ptr_cast и ref_cast. Зачем - я сам тольком не знаю, потому что только бегло просмотрел эти главы книги. Тут же он предлагает реализацию проверки типов во время исполнения путем введения в классы дополнительных виртуальных методов. Зачем он это делает - непонятно, есть ведь оператор typeid. аверное, это очень старая книга, написанная ещё для тех компиляторов, которые не поддерживали информацию о типах во время исполнения.
     
    Добавлено:
    Блин, народ, такую штуку нарыл:
    http://podgoretsky.com/ftp/Docs/Classics/Straustroop/2/Interview.html
    Так что все мы тут фигней страдаем, на самом деле

    Всего записей: 481 | Зарегистр. 04-11-2004 | Отправлено: 16:25 29-01-2007
    Qraizer



    Advanced Member
    Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
    xdude
    Не надо воспринимать всякую юмористическую чушь, которую забыли положить в подкаталог Umor, так всерьёз. Ещё раньше появлялись подобные юморески про Unix и plain-С, причём про последний даже жёстче, чем тут про C++ - "Страуструп" тут хоть не обозвал всех C++ программеров дебилами.
    Новый стиль операторов кастования - в отличие от старого - не только говорит компилятору, какой тип должен получиться в итоге, но и уточняет, зачем тебе этого захотелось. Посмотри:
    Код:
    const int* pci;
    void f(const void*);
    /* ... */
    f((char*)pci);
    Тут на самом деле два преобразования: одно - снятие константности, второе - смена типа указателя. Возникает вопрос: что хотел программист? Три ответа: именно это и хотел; хотел только снять констанстность, но ошибся типом указателя, это нередко бывает при копипасте; хотел только привести тип указателя, но забыл модификатор const. У компилятора нет возможности определить точную конечную цель программиста, поэтому он должен выбрать наиболее общую стратегию поведения, т.е. первый вариант. Новый стиль кастования избавляет от этой недосказанности: static_cast<> - программист имел в виду сменить тип представления данных (оставив его значение неизменным); const_cast<> - программист хотел сменить cv-квалификаторы; reinterpret_cast<> - программист хочет сменить тип данных, не меняя его представления (очень часто это непереносимое кастование; например, char*, будучи откастован к float*, на многих платформах должен будет "выровняться" по кратности float, но не на x86; впрочем, и на x86 это может зависеть от параметров выравнивания, используемых компилятором; поэтому для этого оператора оставили такое длинное и неодобное имя - чтоб чисто психологически пореже хотелось им пользоваться). Кроме этого добавили dynamic_cast<> - для безопасного нисходящего приведения типов, аналога которому в совместимых способах нет, и его приходилось писать вручную или полагаться на авось. Так что теперь компилятор сможет расширит свою диагностику на случаи многих программистких ошибок, связанных с неверным кастованием и которые раньше были неочевидны.
    Цитата:
    ...Компилируется нормально, во время исполнения выкидывает эксепшн St8bad_cast...
    Взять-то ты взял, а выкинул изнутри работу с русской локалью? Когда фасет std::num_get<> выбирается из локали, только там может такое произойти. Вообще не совсем понятно, как он у тебя скомпилится, если выкинуть только то, что ты указал. Там же ещё Ch был. Вообще, приведи полный код функции, который у тебя получился.
    Впрочем, могу попытаться такой вариант предложить:
    Код:
    template<class T> inline
    T from_string2(const std::string &str)
    {
        static ios_base::iostate st = 0;
        static std::stringstream ss;
        T ret_val;
        use_facet<num_get<std::string::value_type, std::string::const_iterator> >(ss.getloc()).get(str.begin(), str.end(), ss, st, ret_val);
        return ret_val;
    }

    Всего записей: 613 | Зарегистр. 08-08-2006 | Отправлено: 21:32 29-01-2007
    Открыть новую тему     Написать ответ в эту тему

    Страницы: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322

    Компьютерный форум Ru.Board » Компьютеры » Прикладное программирование » Вопросы по программированию на C/С++


    Реклама на форуме Ru.Board.

    Powered by Ikonboard "v2.1.7b" © 2000 Ikonboard.com
    Modified by Ru.B0ard
    © Ru.B0ard 2000-2024

    BitCoin: 1NGG1chHtUvrtEqjeerQCKDMUi6S6CG4iC

    Рейтинг.ru