Страницы

Поиск по вопросам

четверг, 5 декабря 2019 г.

Завершение работы приложения

#java #android #android_sdk #activity


Скажите, есть ли возможность командой полностью закрыть приложение, чтобы даже при
долгом нажатии кнопки "домой", оно не высвечивалось в списке приложений? Командой finish()
проблема не решается. Если нет, то как сделать так, чтобы при нажатии на приложение
в списке оно перенаправляло на MainActivity, а не на ту, в которой сработала команда
finish()?
    


Ответы

Ответ 1



В стандартной ситуации достаточно вызвать finish() - активити завершится. Описанный ниже случай нужно использовать только в крайних ситуациях. В мире андроида не принято вручную завершать процессы - всё это должна делать система по своему разумению. //эмулируем нажатие на HOME, сворачивая приложение Intent i = new Intent(Intent.ACTION_MAIN); i.addCategory(Intent.CATEGORY_HOME); i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(i); //в зависимости от версии оси намертво убиваем приложение if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { finishAndRemoveTask(); } else { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { finishAffinity(); } else { finish(); } } //и контрольный в голову Process.killProcess(Process.myPid());

Как сверстать скошеные углы у блоков?

#html #css #media_queries




Народ подскажите как сверстать блоки(div) с кошеными углами на полной версии сайта,
а на планшетной блоки должны быть ровными + в каждом блоке разная картинка в качестве
фона и она заполняет всю область блока.


    


Ответы

Ответ 1



Вот вариант более похожий на то, что в вопросе body { margin: 0; overflow: hidden; } @media (min-width: 600px) { .item { transform: skewX(-15deg); } .content { transform: skewX(15deg); } div.content h1 { transform: rotate(-75deg); } } .accordion { display: flex; } .item { flex: 1; transition: 0.4s; margin-left: -2px; overflow: hidden; display: flex; } .content div { opacity: 0; transition: 200ms; } div.item:hover, div.item:focus { flex: 5; } div.item:hover h1, div.item:focus h1{ opacity: 0; transition: 100ms; } div.item:hover div, div.item:focus div{ opacity: 1; transition: 100ms; } .item:first-child { border-left: 0; flex: 1.25; margin-left: -5em; padding-left: 5em; } .item:last-child { flex: 1.25; margin-right: -5em; padding-right: 5em; } .content { padding: 4em; background-position: 50% 50%; background-size: cover; margin: 0 -5em; flex: 1; display: flex; justify-content: center; } .bg1 { background-image: url("https://i.stack.imgur.com/gW9Md.png"); } .bg2 { background-image: url("https://i.stack.imgur.com/gFeUb.png"); } h1 { color: #fff; font-size: 2em; transform: rotate(-90deg); font-family: monospace; text-align: center; line-height: 1; justify-content: center; } .text { top:0; left:0; width:100%; height:100% }

Агротехника

Легковой
транспорт

Грузоперевозки

Спецтехника

ЖД транспорт



Ответ 2



.button { transform: skewX(-45deg); } .button > div { transform: skewX(45deg); } .button { display: inline-block; padding: .5em 1em; border: 0; margin: .5em; background: #58a; color: white; text-transform: uppercase; text-decoration: none; font: bold 200%/1 sans-serif; }
Click me


Ответ 3



Такой блок с скошенными бордерами, можно сделать с помощью clip-path, угол и сторону можно настраивать отдельно Советую "поиграть с этим свойством" здесь, это поможет #block { width: 200px; height: 400px; -webkit-clip-path: polygon(25% 0%, 100% 0%, 79% 100%, 0% 100%); clip-path: polygon(25% 0%, 100% 0%, 79% 100%, 0% 100%); background: red; }
UPD: Заранее извиняюсь за слабый пример кода

Ответ 4



* { padding: 0; margin: 0; } .skew { -webkit-transform: skewX(-15deg) translate(-50%, -50%); -moz-transform: skewX(-15deg) translate(-50%, -50%); -ms-transform: skewX(-15deg) translate(-50%, -50%); -o-transform: skewX(-15deg) translate(-50%, -50%); transform: skewX(-15deg) translate(-50%, -50%); background-color: blue; position: absolute; top: 50%; left: 50%; width: 250px; }

Hello

World

How's

it

going?



Ответ 5



В этом примере skew включается медиа запросом на ширину экрана $('.info').first().show().animate({ width: '40%' }); $('.item').click(function() { $(this) .next().show().animate({ width: '40%' }) .siblings(".info").animate({ width: 0 }); }); body { overflow: hidden; margin: 0; } @media (min-width: 600px) { .info, .item { transform: skewX(-15deg); } .content { transform: skewX(15deg); } } section { margin-left:50px; text-align:center } .info, .item { height: 150px; float: left; } .item { width: 60px; float:left; background-color: #19B5FE; cursor: pointer; } .info { background-color:#003171; width: 0; display: none; color: #fff }
abc
abc
abc
abc
abc
abc
abc
abc


Гарантирован ли порядок вычисления аргументов в вызове функции?

#cpp #c #функции


К примеру, у меня есть такой вызов функции:

std::unique_ptr tmp{new MyClassWithNameFunction};
foo(tmp->name(), std::move(tmp));


Гарантировано ли, что вызов метода name() будет происходить первым?
    


Ответы

Ответ 1



Порядок вычисления аргументов в вызове функции — это пример неуточняемого поведения (англ. unspecified behavior). Такое поведение зависит от реализации (компилятора), но реализация свой выбор поведения документировать не должна. Кстати говоря, порядок вычисления аргументов необязательно должен быть справа-налево или слева-направо. Более того, при вызове разных функций он может быть разным.

Ответ 2



Нет, не гарантирован. Более того, большинство компиляторов наоборот будут вычислять аргументы справа налево.

Ответ 3



Стандарт. There is a sequence point after the evaluations of the function designator and the actual arguments but before the actual call. Every evaluation in the calling function (including other function calls) that is not otherwise specifically sequenced before or after the execution of the body of the called function is indeterminately sequenced with respect to the execution of the called function. In other words, function executions do not ‘‘interleave’’ with each other. EXAMPLE In the function call (*pf[f1()]) (f2(), f3() + f4()) the functions f1, f2, f3, and f4 may be called in any order. All side effects have to be completed before the function pointed to by pf[f1()] is called. Перевод. Существует точка последовательности после вычисления функции и фактических аргументов, но перед фактическим вызовом. Каждое вычисление в вызывающей функции (включая вызовы других функций), которая иначе специально не упорядочена до или после выполнения тела вызываемой функции, определяется неопределенным образом по отношению к выполнению вызываемой функции. Другими словами, выполнение функций не «перемежается» друг с другом. Пример В вызове функции (*pf[f1()]) (f2(), f3() + f4()) функции f1, f2, f3 и f4 могут вызываться в любом порядке. Все побочные эффекты должны быть завершены до вызова функции, на которую указывает pf[f1()].

Публичные вложенные классы - плохая практика?

#c_sharp #net


Вот смотрю я на некоторые классы стандартных библиотек и думаю, а почему их не сделали
вложенными и публичными, чтобы подчеркнуть их "ареал".

Например, есть DataTable и DataRow. DataRow нигде, вроде, не используется вне контекста
DataTable и более того, отсутствует конструктор => создание возможно только через фабричный
метод. Или DataColumn...

Так почему бы не подчеркнуть принадлежность вынеся классы во внутрь DataTable?

И вообще, вроде, не особо я часто встречал(по моему никогда), что бы использовали
это возможность.

Почему так?
    


Ответы

Ответ 1



Ну почему же, используется, но только для тех типов, которые не особо фигурируют напрямую в коде. Например, List.Enumerator, который используется только неявно кодом, генерируемым компилятором для foreach. Для обычных типов их использовать действительно не рекомендуется, на это даже есть специальное предупреждение анализаторов CA1034. Причина банальна - это неудобно; при каждом использовании такого типа снаружи нужно приписывать имя содержащего типа, сократить используя using нельзя. Ну и с точки зрения архитектуры: вложенность это не просто область видимости, она позволяет вложенному классу работать с private-членами содержащего. Если это не нужно по логике взаимодействия этих классов, лучше не связываться с таким нарушением инкапсуляции.

Ответ 2



Класс в классе увеличивает размер файла. Если в файле более трёхсот строк, с ним уже не очень удобно работать. Если ваш класс становится слишком большим, это подсказывает, что, возможно, нарушен принцип единственной ответственности (single responsibility). Поэтому классы в классах используют только тогда, когда вы передаёте важную информацию для программиста, который будет поддерживать и изменять ваш код. Если класс Bar находится в Foo, значит, он должен знать, как устроен Foo. Пример: реализуем паттерн Memento: Клиент является "посыльным" за Memento, но только исходный объект может сохранять и извлекать информацию из Memento (Memento является "непрозрачным" для клиентов и других объектов). Из описания паттерна мы понимаем, что класс Originator и класс Memento должны знать друг о друге гораздо больше, чем остальные классы. Именно для подчёркивания этого факта нужно разместить один внутри другого. Я бы размещал Memento внутри Originator и вынес бы в него сохранение и восстановление состояния, чтобы оставить в Originator только его основную ответственность. Поскольку в подавляющем большинстве случаев мы всё-таки хотим скрыть детали реализации, мы не используем этот приём слишком часто.

Статья “Stop the CClass idiotism”

#cpp


Несколько лет назад читал статью с таким (примерно) названием. Тема: не прекращается
дебильная практика начинать имена классов с "C" (В TP/Delphi с "T"). Автор - вероятно
американец сербского происхождения. Гугл не помогает (может буквы совсем не те набираю).
Помогите, кто встречал (знает) найти.    


Ответы

Ответ 1



Думаю, Вы имеете в виду вот эту статью: Dejan Jelovic. CStupidClassName

По id vk вернуть имя и фамилию

#android #java #vkontakte_api #вконтакте


Пишу приложение для Android. Есть массив id. Хочу получить имя и фамилию! Авторизироваться
вроде получается, а что дальше?
    


Ответы

Ответ 1



1.Получаешь access_token http://oauth.vk.com/authorize?client_id="ID_приложения"&scope=12&redirect_uri=http://api.vk.com/blank.html&display=touch&response_type=token Получаешь ответ вида: access_token=1543b2375a85aded15b8440eae15cc1506115e715e798cccb2e3c67351ba57f&expires_in=86300&user_id=18791 2.Делаешь запрос: https://api.vkontakte.ru/method/getProfiles?uid=18791&access_token=1543b2375a85aded15b8440eae15cc1506115e715e798cccb2e3c67351ba57f Получаешь ответ {"response":[{"uid":10758791,"first_name":"Вася","last_name":"Пупкин"}]} Если нужен ответ в xml, то https://api.vkontakte.ru/method/getProfiles.xml?uid=18791&access_token=1543b2375a85aded15b8440eae15cc1506115e715e798cccb2e3c67351ba57f Получится 18791 Вася Пупкин для получения информации о нескольких юзерах лучше использовать users.get. Параметр uids - через запятую ID пользователей (до 1000) https://api.vkontakte.ru/method/users.get?uids=123456,321456,369852,741258&access_token=9412a33ddb45b05564751cb2f5940d060599426942689b6a9085feac5ce35a4

Ответ 2



Вы можете провести запрос без авторизации который выглядит следующим образом. https://api.vkontakte.ru/method/getProfiles?uids=твой id&fields=photo В общем Вы можете пользоваться всеми функциями метода getProfiles описанного в докуметации к vk.com api. Таким обазом можно получить имя, фамилию, фотографию пользователя, информацию о том находиться ли он в сети в момент запроса.

Убрать горизонтальный скролл

#html #css


Учусь верстать макет, графика выходит за пределы 1000px.
Желательно сделать так, что бы на мониторе с разрешением экрана 1024x768px не появлялся
горизонатальный скролл, а то, что не влезло, просто оставалось за пределами браузера.
Как этого добиться?    


Ответы

Ответ 1



Добавляем к блоку в котором нужно убрать скролл стиль (в CSS или напрямую) overflow:hidden; overflow-y:hidden; /*для вертикального*/ overflow-x:hidden; /*для горизонтального*/ overflow overflow x overflow y

Ответ 2



#wrapper { width: 980px; overflow: show; } Обычно такого хватает. #wrapper - обертка всего сайта, обычно идет следом за body

Ответ 3



А ещё для IE<8 чтобы убрать прокрутку ничего кроме: не помжет!

Ответ 4



Всё очень просто пишем: html{ width: 100%; max-width: 100%; overflow-x: hidden; } body { width: 100%; max-width: 100%; overflow-x: hidden; }

Ответ 5



контейнеру, в который не влазит контент добавить свойство overflow:hidden; это скроет непомещающиеся части.

Ответ 6



если я правильно понял, то одно из свойств CSS вам должно помочь position: absolute. А также можно поиграться вот с этими свойствами max-width и min-width. Можно еще попробовать обернуть картинку в DIV и этому же DIV`у задать background, и указать размеры картинки которая задана фоном.

Спецификация SVG 1.1 на русском языке

#svg


Где в Интернете можно найти спецификацию SVG 1.1 или SVG 1.2 от W3C.org на русском
языке? Сейчас читаю спецификацию на английском, но так как сроки очень поджимают, решил
спросить, возможно кто-то уже сталкивался с подобной проблемой.
    


Ответы

Ответ 1



update 23.06.2019 г. Добавлен пункт 12. Ответ не будет строго отвечать на поставленный вопрос по простой причине, что нет перевода на русский W3C спецификации SVG. Но будет иметь практическую пользу для людей, которые хотят начать изучать SVG и получить информацию на источники учебной литературы и полезные ссылки на нашем сайте, посвященные некоторым сложным теоретическим вопросам. Вадим Дунаев "Основы SVG" ... скачать Для начала изучения вполне достаточно. Чувствуется, что писал книгу сильный практик. Кратко, но ёмко всё изложено. Множество примеров, показывающих самую суть. Объем книги небольшой, но всё основное, что нужно есть. От простого к сложному. Практически сразу вместе с книгой можно начинать писать свои примеры. Книга в формате pdf выше ссылка на скачивание книги. Как взаимодействуют между собой viewport и viewBox Самый сложный для понимания и одновременно самый нужный, фундаментальный раздел SVG без изучения которого, невозможно создавать адаптивные приложения. Поиск ошибок в приложениях SVG Практические приемы по диагностированию и предотвращению ошибок при создании приложений SVG Как правильно написать формулу path Приведены различные формы записи с комментариями из теории патчей. Практические примеры написания патчей. Как нарисовать автомобиль с помощью команд SVG Это учебный пример. Шаг за шагом будут прорисовываться детали автомобиля и по мере продвижения легко будет понять, как применяются на практике основные команды svg: line, rect, circle, path SVG фильтры Подробно рассматривается вопрос работы с фильтрами SVG feColorMatrix Помогите с dasharray и dashoffset Рассматривается вопрос in-depth stroke-dasharray и stroke-dashoffset от самого простого случая к сложному. Прочитав статью вы можете самостоятельно делать свои примеры, которые востребованы в вебдизайне. Спрайты SVG Раздел имеет десятки вопросов-ответов, в каком-нибудь топике из этого раздела вы точно найдете ответ на свой вопрос по спрайтам. Практические примеры применения масок svg? Теория масок,- кратко и доступно для новичков SVG. Большое количество примеров Как оптимизировать svg код, полученный из векторного редактора Практически весь SVG в примерах и задачах update 23.06.2019 г. Как рассчитать матрицу SVG-преобразования по значениям rotate / translate / scale?

Ответ 2



https://developer.mozilla.org/ru/docs/Web/SVG Да, прибудет с Вами хорошее настроение!!!

Ответ 3



По SVG так и не нашел, но нашел другие спецификации W3C на русском - Русские переводы документов World Wide Web Consortium (W3C). Нашел отличную документацию по SVG на русском языке, возможно, многим будет полезно - SVG синтаксис.

Динамическое имя переменной

#php


$field = 'mailbox';
$default_{$field} = 'abc';

print($default_{'mailbox'});//выводит abc
print($default_mailbox);//Ничего не выводит

P.S. Я уже "вспомнил" про массивы. Но что за такое происходит с именами переменных?    


Ответы

Ответ 1



Может быть такой вариант Вам подойдет: $field = 'mailbox'; ${'default_'.$field} = 'abc'; print($default_mailbox);

Ответ 2



Странно зачем в print передавать аргумент переменной $field какой смысл в переменной то тогда? Переменные, одно слово определяет их суть они должны меняться или быть частью логики вставляться в код станиц и т.д! Менять аргументы переменных возможно от условий описаных в чем-то: цикл, условие, функции и т.д или же присваивать не статическое значение переменной.Для чего переменная если $field статично присвоено mailbox (тем более что это просто строка) и оно же передается в название переменной второй $default_mailbox.Господа где логическая часть выражения??Как аргумент переменной $field будет меняться, при каком условии?Если переменная $field статична значит должна меняться тогда вторая часть названия переменной $default_mailbox иначе смыл переменных теряет свое значение!$default['mailbox'] это выражение так же не имеет смысла если вы используете ключ массива то он должен перебираться каким то циклом например foreach на ключи и аргументы и в переменную передаваться $key иначе нет логики в самом массиве!!

Ответ 3



Странно, что за 5 лет никто так и не ответил, что это одна из возможностей обращения к элементу массива в PHP. RTFM: http://php.net/manual/en/language.types.array.php – находим секцию Note с таким содержанием: Both square brackets and curly braces can be used interchangeably for accessing array elements (e.g. $array[42] and $array{42} will both do the same thing in the example above). А это значит, что следущие две конструкции эквивалентны: $default_{$field} = 'abc'; $default_[$field] = 'abc'; // то же самое Добро пожаловать в мир PHP.

Инициализация массивов

#java #массивы


Почему такая инициализация массива допустима:

int[] array = {1,2,3};


а вот такая нет:

int[] array;
array = {1,2,3};


Вроде бы можно сказать, что способы вполне эквиваленты.
    


Ответы

Ответ 1



Так определено в языке. Синтаксис int[] array = {1,2,3}; — это инициализация, целостное выражение, которое не есть «присваивание array значения {1, 2, 3}», а «инициализация массива значениями 1, 2, 3». А array = {1, 2, 3}; — это присваивание. Но правая часть тут вовсе не определена в языке, инициализатор не имеет самостоятельного смысла. Вы можете, однако, присвоить так: int[] array; array = new int[] {1, 2, 3}; Здесь правая часть new int[] {1, 2, 3} — нормальный, инициализированный объект. В принципе, язык мог бы определить {1, 2, 3} как литерал массива, то есть, чтобы это имело такое же значение, как new int[] {1, 2, 3}. Но дизайнеры языка посчитали это излишним. Мне кажется, они руководствовались таким соображением: для литералов целых чисел (типа 5) нет особой разницы, писать ли int x = 5; int y = 5; или int x = 5; int y = x; А вот для литералов массива (который есть ссылочный тип) разница была бы: вот такой гипотетический код int[] x = {1, 2, 3}; int[] y = {1, 2, 3}; x[0] = 10; System.out.println(y[0]); и int[] x = {1, 2, 3}; int[] y = x; x[0] = 10; System.out.println(y[0]); вели бы себя по-разному! И это приводило бы к ошибкам и недопониманию. Но это лишь мои догадки.

Ответ 2



Фактически, данное предложение array = {1,2,3}; не является инициализацией создаваемого массива. Это предложение выражения с оператором присваивания, причем в правой части имеется конструкция, которая не является выражением. А оператор присваивания требует в правой части от знака = некоторое выражение.

Android Studio пишет, что переменной присвоено значение null, но она нигде не используется

#java #android


Вопрос назрел случайно, когда перешел с Eclipse на AS. Компилятор пишет предупреждение
(указал в топике). Но меня это смущает. Смысл вот в чем. Есть некий класс, я получаю
его экземпляр. Использую его методы. После использования переменную, которая получала
этот экземпляр обнуляю (=null).

MyPreferences pref = new MyPreferences();
pref.loaddata();
...использую методы класса MyPreferences
pref = null;


Вот на последней строчке AS предупреждает. Но раньше я читал такую фразу, что "Android
не любит утечки ресурсов поэтому освобождаем переменную....и присваивали ей null".
Помогите разобраться как правильно писать... спасибо.
    


Ответы

Ответ 1



В том и интерес области видимости и управления памятью в JVM. К примеру, Вы выполняете в своем методе все вышеописанное, после выполнения кода и выхода из метода, ссылки на объект теряются и через время он уничтожается сборщиком мусора. По сути, Вы дописываете лишнее, на что AS и указывает. Совсем другая история, если MyPreferences pref Вы укажете вне метода, переменной класса. Вот тогда pref = null; действительно необходимо для обнуления ссылок для последующего уничтожения объекта сборщиком мусора. private void myMethod() { MyPreferences pref = new MyPreferences(); pref.loaddata(); ...использую методы класса MyPreferences } против public class MyClass extends NotMyClass { MyPreferences pref; ... private void myMethod() { pref = new MyPreferences(); pref.loaddata(); ...использую методы класса MyPreferences pref=null; } }

Ответ 2



Установка null лишь указывает сборщику, что вы объект не используете. Это не вызывает GC сразу же и т.п. Как VAndrJ правильно написал, всё зависит от видимости переменной. Вот только его пример не должен использоваться в реальном проекте: public class MyClass extends NotMyClass { MyPreferences pref; ... private void myMethod() { pref = new MyPreferences(); pref.loaddata(); ...использую методы класса MyPreferences pref=null; } } Это проблема архитектуры. Сложно представить кейс, когда такое могло бы понадобиться. Обычно поля класса живут вместе с самим классом (консистентность, все дела). И когда у вас уже не будет ссылки на сам объект, то всего его внутренние поля будут уничтожены. По поводу же установки переменных в null, порой это даже вредно. Если вы в играх будете всегда явно устанавливать объекты в null, то gc будет работать дольше, так как надо больше освободить. Чтобы оптимизировать в этом отношении игру, необходимо использовать пулы объектов, чтоб gc на них не вызывался вообще. Вообще, почитайте хорошую статью от ibm. В ней ясно дают понять, что порой зануление ссылок может даже сделать хуже.

Ответ 3



принудительно присваивать null, когда поле более не требуется\класс не используется\активити закрывается, нужно только static-полям с завязкой на Context, чтобы избежать утечек памяти, так как имея static на внешний класс, сборщик мусора не уничтожит объект. Так же нужно следить за закрытием курсоров, БД и тп. С остальным разберется сборщик мусора.

Ответ 4



Это ответственность сборщика мусора - находить неиспользуемые более объекты и удалять их. Принудительное обнуление переменных не дает каких-либо преимуществ и просто не имеет смысла, на мой взгляд. Единственный вариант, когда это может потребоваться: при выполнении длительного процесса, когда локальный объект более не требуется, но еще находится в области видимости. Однако, на современных JVM даже такого рода обнуления уже не требуются, поскольку JVM самостоятельно может обрабатывать такого рода случаи. void longProcess() { Object obj = new Object(); operationsWith(obj); obj = null; doSomethingElse(); // длительный процесс, и чтобы не держать в памяти obj, мы ранее ее принудительно обнулили. } Однако этот код может быть написан иначе: void longProcess() { { Object obj = new Object(); operationsWith(obj); } doSomethingElse(); // принудительное обнуление уже не требуется. } По поводу обнуления ссылки, если она является членом класса: по-моему такие поля нужно просто сделать локальными переменными и при необходимости передавать их в функции.

Ответ 5



Многие не понимают, что Java - это чистый pass-by-value. Поэтому ваш pref = null; Означает только то, что переменная pref не указывает на объект в памяти. Что там в действительности произойдет с этим объектом в памяти - зависит от многих факторов. Сама эта инструкция абсолютно бесмысленна и вы можете ее убрать. Если вы ее не можете убрать - у вас ошибка в другом месте.

Каково назначение ключа `-u` при git push?

#git #git_push


И чем отличает отправка без ключа git push origin master.
    


Ответы

Ответ 1



Если сделать git push ветки без ключа -u, Git не свяжет локальную ветку с веткой удалённого репозитория. Последующая операция git pull в этой ветке будет неудачной, так как Git не будет знать, из какой удалённой ветки подтягивать изменения, это придётся указать явно при помощи команды git branch --set-upstream-to=origin/master. Смысл использовать ключ -u есть только при пуше новых веток, для существующих (связанных с удалёнными) веток каждый раз перезаписывать связку необязательно.

Ответ 2



С ключом -u (полный вариант --set-upstream) вы создаёте (если ещё не существует) в удалённом репозитории ветку, соответствующую вашей локальной и связываете их: В remote/branchname будет производиться push в локальную ветку branchname Из remote/branchname будет производиться pull в локальную ветку branchname Для master это актуально, только если вы пушите в пустой репозиторий. Если клонировали - то соответствие ветвей уже настроено. А вот как только вы создадите новую локальную ветвь и захотите её запушить на remote, вам понадобится ключ -u. # есть у нас локальная ветка git checkout -b mybranch # Создаем ветку на remote git push -u origin mybranch # Можно выбрать другое имя для создаваемой ветки на remote. git push -u origin mybranch_with_other_name

Повсеместное использование r-value ссылок

#cpp #cpp11


Стоит ли повсеместно стараться как можно чаще использовать r-value ссылки? Вот, допустим, код:

std::string hi() {
    return "hello world\n"
}

auto&& str = hi();


В данном случае в строке 5 происходит лишь одно создание объекта, и r-value ссылка
на него, и никакого копирования... эффективно, если сравнить, например, с:

auto str = hi();


или

auto str = std::move(hi());


Посему на первый взгляд напрашивается вывод: почему бы не создавать r-value ссылки
как можно чаще вместо обычной инициализации переменной? Особенно если нужно создавать
100000 раз в секунду эти переменные. Допустим, если можно, то писать так:

void function() {
    int&& a = 1;
    double&& b = 2.;
    auto&& value = return_value();
    /*далее какой-то код*/
}


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

void function() {
    int a = 1;
    double b = 2.;
    auto value = return_value();
    /*далее какой-то код*/
}


Поэтому стоит ли как можно чаще пользоваться r-value ссылками вместо обычной инициализации
новых переменных в локальном контексте(внутри функций, например) для эффективности,
или есть ли какие-то встроенные оптимизации, которые при int a = 2 делают те же действия,
что и int&& a = 2?
    


Ответы

Ответ 1



Обычно ссылки хранятся в памяти в виде указателей на объекты. Поэтому в данном предложении auto &&a = 1; будет создан временный объект со значением 1 и ссылка на него. Если у вас есть объявление вида auto a = f(); где функция f возвращает объект некоторого типа T, то этот объект, возвращаемый из функции, строится на месте переменной a , минуя вызов копирующего или перемещающего конструктора. Рассмотрите следующий пример #include struct Int { Int( int x = 0 ) : x( x ) { std::cout << "Int::Int( int )" << std::endl; } Int( const Int &rhs ) : x( rhs.x ) { std::cout << "Int::Int( const Int & )" << std::endl; } Int( Int &&rhs ) : x( rhs.x ) { std::cout << "Int::Int( Int && )" << std::endl; } ~Int() { std::cout << "Int::~Int()" << std::endl; } int x; }; Int f( int x ) { return x; } int main() { auto x = f( 10 ); auto &&y = f( 20 ); return 0; } Вывод на консоль будет следующим Int::Int( int ) Int::Int( int ) Int::~Int() Int::~Int() То есть в обоих случаях будет вызвано по одному конструктору и, соответственно, деструктору. К тому же нельзя создавать, например, массивы из ссылок. В нижеприведенной программе, если раскомментировать предложение с массивом ссылок, то будет выдано сообщение об ошибке. #include struct Int { Int( int x = 0 ) : x( x ) { std::cout << "Int::Int( int )" << std::endl; } Int( const Int &rhs ) : x( rhs.x ) { std::cout << "Int::Int( const Int & )" << std::endl; } Int( Int &&rhs ) : x( rhs.x ) { std::cout << "Int::Int( Int && )" << std::endl; } ~Int() { std::cout << "Int::~Int()" << std::endl; } int x; }; Int f( int x ) { return x; } int main() { Int a[] = { f( 10 ) }; //Int &&b[] = { f( 10 ) }; return 0; }

Ответ 2



На самом деле доступ к переменной напрямую всегда быстрее чем по ссылке. Составим простую программу: int O() { int x = 5; return x; } int test(){ auto&& value = O(); return value; } int test2(){ auto value = O(); return value; } Соберём БЕЗ оптимизаций. test(): push rbp mov rbp, rsp sub rsp, 16 call O() mov DWORD PTR [rbp-12], eax lea rax, [rbp-12] mov QWORD PTR [rbp-8], rax mov rax, QWORD PTR [rbp-8] mov eax, DWORD PTR [rax] leave ret test2(): push rbp mov rbp, rsp sub rsp, 16 call O() mov DWORD PTR [rbp-4], eax mov eax, DWORD PTR [rbp-4] leave ret Как видите работа напрямую - меньше операций сразу, хотя мы переменную и не использовали считай. В общем для примитивов однозначно лучше переменная, для сложных классов - воспользуйтесь профайлером (возможно есть смысл использовать перемещающий конструктор или что-то такое).

Ответ 3



В данном случае нет никакой практической разницы между auto str = hi(); и auto&& str = hi(); В обоих случаях copy elision и return value optimization приводят к тому, что результат функции hi будет формироваться (конструироваться) напрямую в финальном объекте. В первом случае - напрямую в str. Во-втором случае - напрямую во временном объекте, к которому будет привязываться str.

HTML-атрибут role

#html #attribute


Для чего используется HTML-атрибут role? Для кого он указывается? Является ли он
обязательным для HTML-элементов?

P. S. Вопрос «id, class и role к элементу» отвечает только на треть моего вопроса.
    


Ответы

Ответ 1



Данный атрибут используется для семантических тегов, которых появилось большое множество в HTML5. Атрибут role, позволяет наиболее четко указать назначение блока/элемента страницы при взаимодействии пользователя с сайтом. Данный атрибут - не обязательный и по большей части формальный. Основные и наиболее часто используемые значения role: banner - содержит главный заголовок или внутренний заголовок страницы. Например логотип и название сайта. Рекомендуется использовать не больше одного раза на странице. complementary - информационный блок, отделенный от основного содержания ресурса. contentinfo - обобщающая информация о содержании страницы ( к примеру футер сайта ). Рекомендуется использовать не больше одного раза на странице. definition - указывает определение термина или понятия. main - выступает в качестве основного содержания документа. Рекомендуется использовать не больше одного раза на странице. navigation - набор элементов предназначенных для навигации по документу или связанным документам. Рекомендуется использовать не больше одного раза на странице. note - заметка ( вспомогательная информация) к основному содержанию ресурса. search - указывает область для поиска по содержимому.

Ответ 2



Атрибут role с соответствующими значениями используется программами экранного доступа через речевой или тактильный вывод информации. Он задается не только для семантических элементов. Полный перечень значений для всех html-элементов вы можете найти на сайте w3.org

Инициализация static в классе

#cpp #language_lawyer


Может кто-нибудь дать техническое объяснение, почему нельзя инициализировать статические
переменные внутри класса, а в функциях можно? 

Да, я знаю про const static и инициализацию static вне класса, но меня интересует
техническое объяснение этого процесса.

class A
{
public:
    static int a = 10; // нельзя
};




int main()
{
    static int b = 10; // можно
}

    


Ответы

Ответ 1



Это существенно разные вещи с точки зрения языка. В первом случае вы имеете просто объявление статического члена класса с внешним связыванием (external linkage), а во втором - определение статической переменной вообще без связывания (no linkage). Традиционно в С++ определение сущностей c (для которых требуются определения) - это задача пользователя. И инициализатор традиционно (за редкими исключениями) указывается именно в определении. Причина этого заключается в том, что выбор единицы трансляции, в которой будет располагаться определение c внешним связыванием в классическом С++ - это часть пользовательского замысла. Т.е. пользователь выбирает, в какой объектный файл попадет это определение. Также точное место расположения определения статического члена класса определяет его порядок инициализации (и деструкции) в рамках одной единицы трансляции. Это, с точки зрения компилятора, тоже часть пользовательского замысла. Поэтому компилятор ждет этого решения от вас, а не пытается принимать его сам. В С++17 появятся inline-переменные, т.е. фактически возможность при помощи ключевого слова inline сказать компилятору о том, что вас не интересует, где именно будет определен ваш статический член класса. Вот пользуясь эти синтаксисом вы и сможете наконец обойтись без явного указания места определения статического члена и, как следствие, также сможете указывать инициализатор прямо в определении класса class a { public: static inline int a = 10; };

Ответ 2



Внутри определения класса статические члены класса лишь объявляются, а не определяются. Поэтому внутри объявления класса статические члены класса могут иметь неполный тип. Например, #include struct A { static int a[]; }; int A::a[10]; int main() { return 0; } В этой демонстрационной программе в определении класса A объявляется статический член класса - массив a, который имеет неполный тип, то есть количество элементов массива не задано. Имейте в виду, что объявление класса может быть включено во множество единиц трансляции, в то время как определение объекта, включая статические члены класса, должно быть только в одной единице трансляции, если только объект не имеет внутреннее связывание. Кроме того инициализация статических объектов зависит от того, как он расположен относительно других статических объектов. Например, если инициализация некоторого статического объекта зависит от значения другого объекта, то этот статический объект должен быть расположен после того объекта, от которого его инициализация зависит. В функциях вы имеете дело с определениями объектов, если только они не объявлены со спецификатором extern. Но в последнем случае они не могут иметь инициализаторов. А в определениях классов вы имеете дело с объявлениями статических членов, а не с их определениями как объектов. С константными статическими членами классов проблем нет, так как они инициализируются констатными значениями, которые вычисляются на этапе компиляции.

ЗАЧЕМ нужны декораторы? (НЕ как они работают, а ЗАЧЕМ)

#python #декоратор


Зачем нужны декораторы?

Кто читал классическое объяснение про декораторы:

# Декоратор - это функция, ожидающая ДРУГУЮ функцию в качестве параметра
def my_shiny_new_decorator(a_function_to_decorate):
    # Внутри себя декоратор определяет функцию-"обёртку".
    # Она будет (что бы вы думали?..) обёрнута вокруг декорируемой,
    # получая возможность исполнять произвольный код до и после неё.

    def the_wrapper_around_the_original_function():
        # Поместим здесь код, который мы хотим запускать ДО вызова
        # оригинальной функции
        print "Я - код, который отработает до вызова функции"

        # ВЫЗОВЕМ саму декорируемую функцию
        a_function_to_decorate()

        # А здесь поместим код, который мы хотим запускать ПОСЛЕ вызова
        # оригинальной функции
        print "А я - код, срабатывающий после"

    # На данный момент функция "a_function_to_decorate" НЕ ВЫЗЫВАЛАСЬ НИ РАЗУ

    # Теперь, вернём функцию-обёртку, которая содержит в себе
    # декорируемую функцию, и код, который необходимо выполнить до и после.
    # Всё просто!
    return the_wrapper_around_the_original_function

# Представим теперь, что у нас есть функция, которую мы не планируем больше трогать.
def a_stand_alone_function():
    print "Я простая одинокая функция, ты ведь не посмеешь меня изменять?.."

a_stand_alone_function()
# выведет: Я простая одинокая функция, ты ведь не посмеешь меня изменять?..

# Однако, чтобы изменить её поведение, мы можем декорировать её, то есть
# Просто передать декоратору, который обернет исходную функцию в любой код,
# который нам потребуется, и вернёт новую, готовую к использованию функцию:

a_stand_alone_function_decorated = my_shiny_new_decorator(a_stand_alone_function)
a_stand_alone_function_decorated()
#выведет:
# Я - код, который отработает до вызова функции
# Я простая одинокая функция, ты ведь не посмеешь меня изменять?..
# А я - код, срабатывающий после


Далее идет пассаж:


  Наверное, теперь мы бы хотели, чтобы каждый раз, во время вызова
  a_stand_alone_function, вместо неё вызывалась
  a_stand_alone_function_decorated. Нет ничего проще, просто перезапишем
  a_stand_alone_function функцией, которую нам вернул
  my_shiny_new_decorator:


a_stand_alone_function = my_shiny_new_decorator(a_stand_alone_function)
a_stand_alone_function()
#выведет:
# Я - код, который отработает до вызова функции
# Я простая одинокая функция, ты ведь не посмеешь меня изменять?..
# А я - код, срабатывающий после


Т.е. после этого пассажа - мы теряем возможность вызвать функцию в первоначальном
виде. Теперь она ВСЕГДА декорирована.

И вопрос, зачем тогда декоратор был нужен?

1) Почему бы (если мы все равно теряем первоначальную функцию) просто не переписать
изначальную функцию? (просто дописав в начале и в конце функции необходимые нам куски
кода). Вот так:

def a_stand_alone_function():
    print "Я - код, который отработает до вызова функции"
    print "Я простая одинокая функция, ты ведь не посмеешь меня изменять?.."
    print "А я - код, срабатывающий после"


или, если дополнительный код большой и должен лежать отдельно, то:

def a_stand_alone_function():
        pre_function()
        print "Я простая одинокая функция, ты ведь не посмеешь меня изменять?.."
        post_function()


2) Зачем вся эта свистопляска, вместо того, чтобы сделать простое решение, как в
1 вопросе?

3) Я бы еще понял декораторы, если бы была возможность вызывать как декорируемую,
так и изначальную функцию. Но декораторы, написанные с @ этого не позволяют. Зачем
декоратор затирает оригинальную функцию?

Буду очень благодарен за ответ с объяснениями и, может быть, ПОНЯТНЫМИ примерами
из реальной практики.
    


Ответы

Ответ 1



Например, в Django декораторы широко используются. Вместо того, чтобы изобретать велосипед и в каждой функции-контроллере, которая должна быть доступна только авторизованным пользователям, писать свой код проверки авторизации, просто декорируем её, соответствующим декоратором. А если нужно ещё гарантировать, что функция будет применяться только для запросов определённого типа? И что вся работа с БД в функции будет выполняться в транзакции? Если весь код тянуть в функцию, то вскоре её изначальный смысл просто потеряется в куче шаблонного кода. А она ведь ещё и не одна в модуле, и для каждой придётся написать этот шаблонный код, повторив его множество раз. Вместо того, чтобы просто написать: @require_POST @login_required @transaction_atomic def some_view(request): ...

Ответ 2



В дополнение к ответу @Sergey Gornostaev: Декораторы — по сути реализация аспектно-ориентированного программирования в Питоне. Вы определяете логику или функциональность отдельно от функций, которые будут пользоваться этой функциональностью. Возможно, эту логику разрабатывает для вас другая команда. Пример с логированием, который вы видели практически везде, или те же транзакции — один из возможных примеров аспекта-функциональности. Затем вы влёгкую можете подключить использование этого аспекта без ручного переписывания функций, просто добавлением или убиранием атрибута. В любом случае, атрибут — часть вашего исходного кода. Если вы хотите, чтобы недекорированная функция была доступна, вы можете просто не ставить декоратор. Или иметь отдельно недекорированную функцию, и отдельно её декорированный вариант, который вызывает недекорированный. Или дописать функциональность, которую вносил декоратор, вручную (но в этом случае вам нужно будет обновить ваш код, если в декораторе произойдут изменения, например, багфикс; это обычная проблема дубляжа кода.) Декоратор просто позволяет вам добавлять функциональность легко.

Ответ 3



# во первых ссылку на функцию можно получить из декоратора # во вторых теперь эти "куски кода в декораторе" дописать можно к любой функции, например логирование, проверка аргументов перед вызовом def decor(fn): '''декоратор''' def wrapper(*args, **kwargs): if all(args): out = fn(*args, **kwargs) with open('file.txt', 'a') as log: log.write('{} {} {} {}'.format(fn, args, kwargs, out)) print('декоратор', end=' ') return out return wrapper @decor def func(*args): '''@декоратор(изначальная функция)''' return sum(args) func(1, 2, 3) # вызывать как декорируемую original_fn = func.__closure__[0].cell_contents # func без декоратора original_fn(1, 2, 3) # вызывать как изначальную функцию # или import inspect original_fn = inspect.getclosurevars(func).nonlocals['fn'] original_fn(0, 2, 3) # если постоянный вызов дероратора не требуется, изначальную функцию не стоит декорировать @decor def func2(*args): '''изначальная функция''' return sum(args) func2(1, 2, 3) # вызывать как изначальную функцию decor(func2)(1, 2, 3) # вызывать как декорируемую

Захват значений в лямбда-выражении

#java #лямбда_выражение



  Лямбда-выражения должны использоваться для захвата значений, а не переменных. Захват
значений побуждает писать код без побочных эффектов, поскольку альтернатива труднее.


Что понимается под захватом значений в лямбда-выражении?
    


Ответы

Ответ 1



Это значит, что в лямбда-выражениях стоит использовать внешние (относительно выражения) неизменяемые значения, а не внешние переменные, значение и внутреннее состояние которых могут меняться. Под внешними неизменяемыми значениями, соответственно, подразумеваются effectively final локальные переменные и поля примитивных типов, а также effectively final объекты, внутреннее состояние которых не будет меняться. Связано это с тем, что Streams и лямбда-выражения проектировались из расчета на их многопоточное использование. Проблема с использованием переменной (counter) вместо значения видна в таком примере: private static class Element { private final int value; public Element(int value) { this.value = value; } public int getValue() { return value; } } private static volatile int counter = 0; public static void main(String[] args) { List list = new ArrayList<>(); for (int i = 0; i < 100 * 1000; i++) { list.add(new Element(1)); } list.parallelStream().forEach(e -> counter += e.getValue()); System.out.println(counter); } Рассчитывать на то, что на экран будет выведено значение 100000, не приходится, потому что налицо race condition. В моём тесте этот код смог получить правильное значение только в 299 случаях из 100 тысяч. Это одна из причин почему локальные переменные, используемые в лямбда-выражении, должны быть effectively final. Допустимость кода int localCounter = 0; list.parallelStream().forEach(e -> localCounter += e.getValue()); Привела бы к race condition для локальной переменной, что стало бы новым витком проблем в многопоточном программировании на Java. Локальные переменные считаются потокобезопасными, и ломать этот принцип разработчикам Java не хотелось. Можно "обдурить" компилятор в плане ограничения на effectively final значение таким образом: int[] localCounter = { 0 }; list.parallelStream().forEach(e -> localCounter[0] += e.getValue()); System.out.println(localCounter[0]); Так что "выстрелить себе в ногу" при использовании effectively final локальной переменной всё же можно. Конечно, не стоит удивляться тому, что значение опять-таки будет посчитано неправильно. На практике так делать определённо не стоит. Да, здесь можно использовать AtomicInteger: AtomicInteger atomicInteger = new AtomicInteger(); list.parallelStream().forEach(e -> atomicInteger.addAndGet(e.getValue())); System.out.println(atomicInteger.get()); Однако это убивает всю идею распараллеливания кода. В данном случае предполагается использование связки из map и reduce: int localCounter = list.parallelStream().map(e -> e.getValue()).reduce(0, (a, b) -> a + b); System.out.println(localCounter); Часть с map и reduce можно записать и так: .map(Element::getValue).reduce(0, Integer::sum) Статью Brian Goetz (автора книги "Java Concurrency in Practice") по этому поводу можно прочитать здесь. Однако проблемы при захвате переменных вместо значений могут возникать не только при параллельном выполнении. Например: private static class Element { public int x; public Element(int x) { this.x = x; } public Function getMapper() { return (e -> e + x); } } public static void main(String[] args) { Element element = new Element(2); List list1 = Arrays.asList(10, 20, 30); Function function1 = element.getMapper(); element.x = 4; List list2 = Arrays.asList(10, 20, 30); Function function2 = element.getMapper(); list1 = list1.stream().map(function1).collect(Collectors.toList()); list2 = list2.stream().map(function2).collect(Collectors.toList()); System.out.println(list1); System.out.println(list2); } В данном коде происходит захват переменной (не effectively final поля) x, из-за чего вместо ожидаемого вывода [12, 22, 32] [14, 24, 34] будет выведено [14, 24, 34] [14, 24, 34] При захвате же значения: public Function getMapper() { int n = x; return (e -> e + n); } такой проблемы/ошибки не возникнет.

Ответ 2



Наверное, автор имел ввиду, что лямбда-выражения должны трогать не переменные, а принимать на вход значение и отдавать значения на выходе. Например: Плохо: final String string = "string"; class.method(() -> string += "abc"); Хорошо: class.method((string) -> string += "abc");

Закрасить текст, слово, букву

#c_sharp #wpf


Доброго времени суток.

WPF Разрабатываю караоке плеер. Основную часть сделал. Получаю текст и музыку всё
проигрываю всё хорошо) Встала задача теперь все это дело красиво вывести, как в настоящем
караоке. что бы две строчки и текст закрашивать постепенно по тайм коду. 

Так вот и вопрос как сделать красиво закрасить текст. Что для этого можно использовать?
Подскажите, направьте. Заранее спасибо. 
    


Ответы

Ответ 1



Вот вам решение с контурами букв и побуквенной постепенной заливкой. Идея решения одолжена из комментария @S.Kost и здесь. Для начала определим наш XAML. Определяем невидимый TextBlock с текстом. Мы стащим из него свойства, и отрендерим текст самостоятельно. Почему нельзя было использовать видимый TextBlock? Дело в том, что он не умеет отрисовывать границу глифов, а мы хотим в начале, чтобы буквы были «пустыми». Под ним в том же Grid'е кладём Path, который и будет содержать наш текст. У него есть Stroke, задающий границу, установим его цвет в чётный и толщину в пол-пикселя. Затем, в заполнении кладётся наша градиентная заливка. Кладём 2 контрольных точки, которые будут пробегаться по каждой букве. Слева от первой точки будет чёрная, справа — белая заливка. Между точками — переход. Затем, анимация. Мы анимируем продвижение контрольных точек вдоль букв. Откуда и докуда происходит анимация, устанавливается в code-behind. С XAML'ом покончено, теперь code-behind. Для начала, нам нужна функция, которая вытащит из текста его геометрию, и измерит ширины всех букв. Заодно пропустим пробелы, их анимировать не стоит. Для измерения геометрии текста воспользуемся удобным классом FormattedText. double extent; // общая ширина текста List boundingBoxes; // прямоугольники с каждым символом void Create() // https://msdn.microsoft.com/en-us/library/ms745816(v=vs.110).aspx { TextBlock tb = Source; var text = tb.Text; FormattedText formattedText = new FormattedText( text, CultureInfo.GetCultureInfo("en-US"), FlowDirection.LeftToRight, new Typeface( tb.FontFamily, tb.FontStyle, tb.FontWeight, tb.FontStretch), tb.FontSize, Brushes.Black // конкретная кисть нам не важна, мы используем только геометрию ); // стащили геометрию у текста... var geo = formattedText.BuildGeometry(new Point()); // ...и отдали её Path'у Target.Data = geo; var bb = formattedText.BuildHighlightGeometry(new Point()); extent = bb.Bounds.Width; // общая ширина boundingBoxes = // побуквенная ширина и позиции Enumerable.Range(0, text.Length) .Where(k => !char.IsWhiteSpace(text[k])) .Select(k => formattedText.BuildHighlightGeometry(new Point(), k, 1) .Bounds) .ToList(); } Ну и нам нужна функция, запускающая в цикле для каждой буквы анимацию. Это совсем просто: async void Play() { var storyboard = (Storyboard)Target.Resources["AnimationStoryboard"]; var fromAnimation = (DoubleAnimation)storyboard.Children[0]; var toAnimation = (DoubleAnimation)storyboard.Children[1]; foreach (var b in boundingBoxes) { await Task.Delay(250); // перерыв между буквами fromAnimation.From = b.Left / extent; fromAnimation.To = b.Right / extent; toAnimation.From = b.Left / extent; toAnimation.To = b.Right / extent; storyboard.Begin(); await Task.Delay(250); // дождёмся конца анимации } } Результат:

Ответ 2



Посмотрите в сторону RichTextBox. Позволяет получить часть текста TextRange и отформатировать методом ApplyPropertyValue.

Ответ 3



Можете исползовать The TextBlock control - Inline formatting TextBlock tb = new TextBlock(); tb.TextWrapping = TextWrapping.Wrap; tb.Margin = new Thickness(10); tb.Inlines.Add("An example on "); tb.Inlines.Add(new Run("the TextBlock control ") { FontWeight = FontWeights.Bold }); tb.Inlines.Add("using "); tb.Inlines.Add(new Run("inline ") { FontStyle = FontStyles.Italic }); tb.Inlines.Add(new Run("text formatting ") { Foreground = Brushes.Blue }); tb.Inlines.Add("from "); tb.Inlines.Add(new Run("Code-Behind") { TextDecorations = TextDecorations.Underline }); tb.Inlines.Add(".");

Объясните выхлоп асма: откуда $8583909746840200520 при создании “Hello, world!\n”

#cpp #ассемблер


Не могу понять ассемблерный код, получаемый в результате компиляции простейшей программы:

int main(int argc, char* argv[]) {
    char str[] = "Hello, world!\n";
}


При использовании gcc6.3 x86_64 получается такой результат:

main:
    pushq   %rbp
    movq    %rsp, %rbp
    movl    %edi, -20(%rbp)
    movq    %rsi, -32(%rbp)
    movabsq $8583909746840200520, %rax
    movq    %rax, -16(%rbp)
    movl    $1684828783, -8(%rbp)
    movw    $2593, -4(%rbp)
    movb    $0, -2(%rbp)
    movl    $0, %eax
    popq    %rbp
    ret


Откуда берётся $8583909746840200520? 

Замечу, что если написать так:

int main(int argc, char* argv[]) {
    char str[] = "Hello, world!\0";
}


то получается совсем другое:

.LC0:
    .string "Hello, world!"
    .string ""
main:
    pushq   %rbp
    movq    %rsp, %rbp
    movl    %edi, -20(%rbp)
    movq    %rsi, -32(%rbp)
    movq    .LC0(%rip), %rax
    movq    %rax, -16(%rbp)
    movl    .LC0+8(%rip), %eax
    movl    %eax, -8(%rbp)
    movzwl  .LC0+12(%rip), %eax
    movw    %ax, -4(%rbp)
    movzbl  .LC0+14(%rip), %eax
    movb    %al, -2(%rbp)
    movl    $0, %eax
    popq    %rbp
    ret

    


Ответы

Ответ 1



8583909746840200520(dec) == 77202C6F6C6C6548(hex) == "w ,olleH"(str), второе гигантское число - остаток строки.

Что такое BDD в чём его отличия от TDD?

#тестирование #терминология


Что такое BDD  и в чём его отличия от TDD?
    


Ответы

Ответ 1



BDD - behaviour-driven development - это разработка, основанная на описании поведения. То есть, есть специальный человек(или люди) который пишет описания вида "я как пользователь хочу когда нажали кнопку пуск тогда показывалось меню как на картинке". (там есть специально выделенные ключевые слова). Программисты давно написали специальные тулы (например, cucumber), которые подобные описания переводят в тесты (иногда совсем прозрачно для программиста). А дальше классическая разработка с тестами. В чем преимущество BDD? тесты читаемые для не программистов. их легко изменять. Они часто пишутся почти на чистом английском. их теперь может писать product owner или другие заинтересованные лица. результаты выполнения тестов более "человечные". тесты не зависят от целевого языка программирования. Миграция на другой язык сильно упрощается. (слово тесты выделено не случайно, потому что теперь тесты это и описания, и непосредственно их реализация.)

Ответ 2



BDD фреймворки увеличивают время разработки тестов, так как добавляются новые зависимости усложняют поддержку тестов, так как теперь больше уровней абстракций, которые нужно поддерживать никакие бизнес аналитики не могут писать BDD тесты потому что во-первых они просто не будут этого делать а во-вторых нельзя просто написать в свободной форме на английском тест и все заработает. Нужно строго соблюдать синтаксис и надо знать все кейворды и в каком порядке они будут работать. И надо замаппить actions на эти кейворды на каком-то ЯП Таким образом все преимущества продвигаемые BDD фреимворками как-то написание тестов на естественном языке не техническими людьми в реальности не применимы.

Ответ 3



Прошу сильно не минусовать, ниже - шутка: BDD - bug-driven development, разработка на багах. Когда придумана новая фича, делается декомпозиция, и сразу на тестирование. Тесты не проходят (ведь никто еще ничего не реализовывал), и заводится баги. Команда начинает фиксить баги, закрывая функционал.

Стилизовать input type=range перед ползунком

#html #css #input


Здравствуйте! Есть такие стили для слайдера:



input[type=range] {-webkit-appearance: none; margin: 5.8px 0; background-color: transparent
!important;}

input[type=range]:focus {outline: none;}

input[type=range]::-webkit-slider-runnable-track {cursor: pointer; box-shadow: 2.4px
2.4px 6.2px rgba(7, 7, 163, 0.72), 0px 0px 2.4px rgba(8, 8, 187, 0.72); background:
#ac62ff; border-radius: 21.6px; border: 1px solid rgba(163, 0, 255, 0.79);}

input[type=range]::-webkit-slider-thumb {box-shadow: 2.4px 2.4px 9.5px rgba(4, 16,
14, 0.78), 0px 0px 2.4px rgba(9, 36, 32, 0.78); border: 1.8px solid rgba(0, 0, 6, 0.77);
border-radius: 28px; background: #ffff29; cursor: pointer; -webkit-appearance: none;
margin-top: -7.8px;}

input[type=range]:focus::-webkit-slider-runnable-track {background: #b16cff;}

input[type=range]::-moz-range-track {width: 100%; cursor: pointer; box-shadow: 2.4px
2.4px 6.2px rgba(7, 7, 163, 0.72), 0px 0px 2.4px rgba(8, 8, 187, 0.72); background:
#ac62ff; border-radius: 21.6px; border: 1px solid rgba(163, 0, 255, 0.79);}

input[type=range]::-moz-range-thumb {box-shadow: 2.4px 2.4px 9.5px rgba(4, 16, 14,
0.78), 0px 0px 2.4px rgba(9, 36, 32, 0.78); border: 1.8px solid rgba(0, 0, 6, 0.77);
border-radius: 28px; background: #ffff29; cursor: pointer;}

input[type=range]::-ms-track {width: 100%; cursor: pointer; background: transparent;
border-color: transparent; color: transparent;}

input[type=range]::-ms-fill-lower {background: #a758ff; border: 1px solid rgba(163,
0, 255, 0.79); border-radius: 43.2px; box-shadow: 2.4px 2.4px 6.2px rgba(7, 7, 163,
0.72), 0px 0px 2.4px rgba(8, 8, 187, 0.72);}

input[type=range]::-ms-fill-upper {background: #ac62ff; border: 1px solid rgba(163,
0, 255, 0.79); border-radius: 43.2px; box-shadow: 2.4px 2.4px 6.2px rgba(7, 7, 163,
0.72), 0px 0px 2.4px rgba(8, 8, 187, 0.72);}

input[type=range]::-ms-thumb {box-shadow: 2.4px 2.4px 9.5px rgba(4, 16, 14, 0.78),
0px 0px 2.4px rgba(9, 36, 32, 0.78); border: 1.8px solid rgba(0, 0, 6, 0.77); border-radius:
28px; background: #ffff29; cursor: pointer;}

input[type=range]:focus::-ms-fill-lower {background: #ac62ff;}

input[type=range]:focus::-ms-fill-upper {background: #b16cff;}

/* Track */
input[type=range]::-webkit-slider-runnable-track {height: 6.4px;}
input[type=range]::-moz-range-track {height: 6.4px;}
input[type=range]::-ms-track {height: 6.4px;}

/* Thumb */
input[type=range]::-webkit-slider-thumb {height: 20px; width: 8px;}
input[type=range]::-moz-range-thumb {height: 20px; width: 8px;}
input[type=range]::-ms-thumb {height: 20px; width: 8px;





Моя задача – поменять цвет слайдера перед тумблером. Как это сделать?

Если не понятно, то могу привести пример.
    


Ответы

Ответ 1



Вот пример стилей где цвета до и после ползунка различаются: input[type='range'] { overflow: hidden; width: 80px; -webkit-appearance: none; background-color: #9a905d; } input[type='range']::-webkit-slider-runnable-track { height: 10px; -webkit-appearance: none; color: #13bba4; margin-top: -1px; } input[type='range']::-webkit-slider-thumb { width: 10px; -webkit-appearance: none; height: 10px; cursor: ew-resize; background: #434343; box-shadow: -80px 0 0 80px #43e5f7; } input[type="range"]::-moz-range-progress { background-color: #43e5f7; } input[type="range"]::-moz-range-track { background-color: #9a905d; } input[type="range"]::-ms-fill-lower { background-color: #43e5f7; } input[type="range"]::-ms-fill-upper { background-color: #9a905d; }

Ответ 2



Как я понял вам нужно без overflow: hidden; на input. Вот рабий пример и для этого: .range_container{ position: relative; width: 80px; /*input range width*/ height: 10px; /*input range height*/ overflow: hidden; } input[type='range'] { position: absolute; width: 80px; height: 9px; -webkit-appearance: none; background-color: #9a905d; top: -2px; left: -2px; } input[type='range']::-webkit-slider-runnable-track { height: 10px; -webkit-appearance: none; color: #13bba4; margin-top: 1px; } input[type='range']::-webkit-slider-thumb { width: 10px; -webkit-appearance: none; height: 10px; cursor: ew-resize; background: #434343; box-shadow: -80px 0 0 80px #43e5f7; } input[type="range"]::-moz-range-progress { background-color: #43e5f7; } input[type="range"]::-moz-range-track { background-color: #9a905d; } input[type="range"]::-ms-fill-lower { background-color: #43e5f7; } input[type="range"]::-ms-fill-upper { background-color: #9a905d; }


Вложенность BEGIN END

#sql_server


Как легко находить вложенности разных блоков друг в друга в большом, уже имеющемся
в беспорядке, объёме кода? Например, вот в таком коде, меня интересует вложенность
значительно сложнее:

BEGIN

SELECT @@VERSION

BEGIN

SELECT @@VERSION

BEGIN 

SELECT @@VERSION

END

BEGIN

SELECT @@VERSION

END
END
END

    


Ответы

Ответ 1



Начиная с SQL Server Management Studio 2008 версии в стандартной функциональности IntelliSense существует функциональность структурирования кода, когда на левом поле окна редактора появляется возможность сворачивания/разворачивания блоков кода, подробнее по ссылке Для активации данной возможности необходимо зайти в меню Сервис -> Параметры и в окне настроек выбрать пункт Текстовый редактор -> Transact SQL -> IntelliSense: 1. Поставить галку Включить использование технологии IntelliSense 2. Далее поставить галку на Определить структуру инструкций. Редактор запросов компонента Database Engine формирует структурные области для каждого элемента в следующей иерархии. Пакеты. Первый пакет содержит код от начала файла до первой команды GO либо до конца файла, если он не содержит команд GO. Каждый последующий пакет после первой команды GO охватывает код от соответствующей команды GO до следующей команды GO, либо до конца файла. Блоки, разделяемые следующими ключевыми словами: BEGIN — END BEGIN TRY — END TRY BEGIN CATCH — END CATCH Многострочные инструкции.

Ответ 2



В SqlServer Management Studio (да и в Visual Studio) понять какой END c каким BEGIN связан поможет сочетание клавиш Ctrl + }. Работает также с блоками BEGIN TRY ... END TRY, BEGIN CATCH ... END CATCH.

Ответ 3



Для определения уровня вложенности используйте оформление кода, отступы и переносы.

Ответ 4



Расширение SSMSboost для SQL Server Management Studio форматирует всё красиво. Одна кнопка все отступы делает. Правда он ещё и все перечисления полей делает с каждой строки. Так что если код огромный, то будет ещё больше, но нагляднее

Объявление функции, похожее на создание объекта

#cpp


class Test { };

int main(int argc, char* argv[])
{
    Test t(); // Что делает этот оператор

    return 0;
}

    


Ответы

Ответ 1



Это частный пример явления, известного в С++ под именем "most vexing parse". В ситуациях, когда в объявлении возникает неоднозначность между определением объекта и объявлением функции, эта неоднозначность в С++ разрешается в пользу объявления функции. В вашем случае имеет место простейший пример именно такой неоднозначности. В соответствии с вышеприведенным правилом, данное объявление трактуется как объявление функции t, не имеющей параметров и возвращающей значение типа Test. Для определения именно объекта c выполнением value-инициализации можно воспользоваться современным (С++11 и далее) синтаксисом униформной инициализации, который не страдает от этой неоднозначности Test t{}; Хотя в случае именно вашего (т.е. "пустого") класса Test явный инициализатор не имеет никакого значения вообще и можно просто написать Test t;

Ответ 2



Как я понимаю это объявление функции с прототипом Test t(); в зоне видимости main.

Использование global в Python

#python


Здравствуйте, знакомлюсь с python и после c++ категорически не понимаю  принцип использования
global переменных. Если у переменной, находящейся в def указать  global то можно ли
её значение использовать вне этой функции, у меня точно не получается. Может просто
потому что я новичок и очевидные вещи для меня еще слишком сложны.

def check():
    global urokb_in
    urokb_in = 1
    with open('users.txt', 'r') as f:
        line = f.readline()
        f.close()
    with open('progress.txt', 'r') as k:
        while True:
            global uroka_in
            lines = k.readline()
            if line == lines.rstrip():
                uroka_in = int(k.readline().rstrip())
                urokb_in = uroka_in + 1
                uroka_str = str(uroka_in)
                urokb_str = str(urokb_in)
                lines.replace(uroka_str, urokb_str)
                k.close()
                break
            if not lines:
                k.close()
                urokb_in = 1
                with open('progress.txt', 'a') as j:
                    j.write(line)
                    j.write('\n')
                    j.write(str(urokb_in))
                    j.write('\n')
                    j.close()
                    break
    if urokb_in == 1:
       educate__scr = PhotoImage(file='e_scr_1.png')
       educate_label = Label(root, image=educate__scr)
       educate_label.place(x=0, y=0)


Более опытные кодеры подскажите как исправить.
SyntaxError: name 'urokb_in' is used prior to global declaration
    


Ответы

Ответ 1



Если не указать global или nonlocal, то x = внутри функции создаёт локальную переменную. Если вы хотите новую глобальную переменную создать/или переопределить старую внутри функции (не на глобальном уровне), то можно global использовать. Это может быть полезно при работе с multiprocessing модулем, чтобы унаследовать желаемые глобальные переменные от родительского процесса: def init(shared_arr_): global shared_arr shared_arr = shared_arr_ # must be inherited, not passed as an argument Полный пример кода. Если вы хотите просто использовать существующую глобальную переменную, не переопределяя её, то global не нужен (иначе к примеру, пришлось бы в каждой функции каждый используемый модуль, каждую глобальную функцию объявлять global). я новичок и очевидные вещи для меня еще слишком сложны Для новичков: не переопределяйте глобальные переменные вообще, то есть избегайте global. Считайте каждое появление global в коде ошибкой, если нет особых причин для использования этой конструкции (как в примере с multiprocessing). Если не получается избавится от global, то создайте минимальный пример кода и задайте отдельный вопрос: "как избавиться от global, делая X"

Ответ 2



Инструкция global используется там где необходимо явно указать на то, что следует использовать объект из глобальной области видимости (namespace модуля или словарь globals) и отменяет стандартный механизм поиска для переменной (LEGB), дополнительно к этому даёт возможность изменения объекта не в своей области видимости. требует дисциплины в общем то, так как если до объявления global a во вложенной области видимости имени а не было в OВ globals() она будет создана при первой операции присваивания и не пропадёт при завершении работы (к примеру функции). dir() # ['__builtins__'] def foo(): global a a = 22 pass dir() # ['__builtins__', 'foo'] # foo необходимо вызвать. foo() dir() # ['__builtins__', 'a', 'foo'] a # 22 # а теперь живет в globals() def foo1(): print(a) foo1() # 22 # по правилу LEGB имя а было найдено в globals() def foo2(): a += 4 pass foo2() # Traceback (most recent call last): # File "", line 1, in # File "", line 2, in foo2 # UnboundLocalError: local variable 'a' referenced before assignment # запрещено изменение переменных не в своей области видимости для этого # требуется сначала указать что нужно изменить именно a из globals() def foo3(): global a a += 4 foo3() a # 26

Ответ 3



Указывать глобальную переменную нужно непосредственно в теле функции в самом начале, например: x = 1 def set_value(): global x x = 2 print(x) >>> 1 set_value() print(x) >>> 2

Что такое rvalue и lvalue?

#cpp


На разных ресурсах нашел разные определения rvalue, lvalue. 
Как же правильно? 

right value или read value? 

left value или locator value? 
    


Ответы

Ответ 1



Исходно речь шла про правую и левую части относительно оператора присваивания. Но правильного варианта такой простой расшифровки нет и быть не может. Термины так и останутся rvalue и lvalue. А вот какой в них вложен смысл чётко прописано в стандарте. Всё это образует категории выражений. glvalue Выражение, чьё вычисление определяет сущность объекта, битового поля или функции. prvalue Выражение, чьё вычисление инициализирует объект, битовое поле или вычисляет значение операнда оператора, с соответствии с контекстом использования. xvalue Это glvalue, которое обозначает объект или битовое поле, чьи ресурсы могут быть повторно использованы (обычно потому, что они находятся около конца своего времени жизни). lvalue Это glvalue, которое не является xvalue. rvalue Это prvalue или xvalue. Таким образом любое выражение есть в первую очередь lvalue, xvalue или prvalue. rvalue - это уже обобщение.

Ответ 2



Не знаю, что Вы имеете ввиду под вопросом "как правильно". rvalue и lvalue - это категории выражений. Вот что написано в стандарте: — A glvalue is an expression whose evaluation determines the identity of an object, bit-field, or function. — A prvalue is an expression > whose evaluation initializes an object or a bit-field, or computes the value of the operand of an operator, as specified by the context in which it appears. — An xvalue is a glvalue that denotes an object or bit-field whose resources can be reused (usually because it is near the end of its lifetime). — An lvalue is a glvalue that is not an xvalue. — An rvalue is a prvalue or an xvalue. //... [Note: Historically, lvalues and rvalues were so-called because they could appear on the left- and right-hand side of an assignment (although this is no longer generally true); glvalues are “generalized” lvalues, prvalues are “pure” rvalues, and xvalues are “eXpiring” lvalues. Despite their names, these terms classify expressions, not values. — end note]

Методы оптимизации, основанные на эффективном использовании оборудования

#алгоритм #оптимизация


А давайте соберём здесь неалгоритмические методы оптимизации программ. Не алгоритмы
«N*log n вместо N^2», а приёмы позволяющие использовать имеющееся оборудование более
эффективно. Что приходит на ум мне:

Использование кэша процессора:


Обработка данных небольшими порциями, чтобы каждый раз все необходимые данные влезали
в кэш. 
Пример (для начала; можно придумать что-то более удачное): для quicksort эта рекомендация
выполняется, когда дело доходит до небольших блоков. Но на больших объёмах данных на
первых итерациях сортируемые и сливаемые половинки не помещаются в кэш. Следствие:
если, допустим, помимо сортировки надо с данными сделать что-то ещё, это выгодно делать
после сортировки каждого небольшого блока, пока данные ещё в кэше.


Обход латентности доступа к данным (применимо и к чтению/записи данных процессором
из памяти и к работе с диском):


Чтение/запись данных последовательно, а не в случайном порядке. Пример: внешняя сортировка
позволяет обойтись эффективными операциями чтения/записи больших последовательных блоков
данных. Если реализовать quicksort с хранением данных на диске, то при объёме данных
> объёма кэша потребуется O(n * log n) движений головки диска. 
Буферизация ввода/вывода. Пример: всё та же внешняя сортировка. Одна из операций
там – слияние данных из нескольких файлов с диска и запись результата на диск. Это
будет работать гораздо быстрее, если читать данные из каждого входного файла порциями,
скажем, по 10 МБ и писать результаты в буфер, который сбрасывать на диск тоже по мере
накопления.
Группировка нужных данных. Пример: параллельные массивы. Допустим, у нас есть большой
массив точек на плоскости и описание к каждой из них длиной 50 символов. Тогда, например,
выбор точек, попадающих в некоторый прямоугольник (допустим, нам невыгодно применять
что-то более сложное, чем простой проход по массиву) будет работать существенно быстрее,
если разбить информацию на два массива:

struct THeader {  int x, y;  };
struct TInfo {  char description[50];  };
THeader dotHeaders[10000000], dotInfos[10000000];

Другой похожий пример (вопрос Примеры оптимизации путём группировки данных в памяти).


Оптимальное использование имеющейся пропускной способности:


Сжатие данных «на лету». Пример: объёмная база данных с некоторыми  закономерностями
в данных (между полями записей или между соседними записями). Сжатие данных перед записью
на диск и расжатие при чтении может позволить достичь большей скорости записи/чтения
с диска.
Использование специальных команд процессора, содержащих дополнительные "подсказки"
по работе с памятью. Пример: intrinsic'и _mm_stream_ps и т.п. в примере http://pastebin.com/Xzq9dYww
@superhackkiller1997'a. _mm_stream_ps компилируется в команду MOVNTPS - аналог memset,
работающий в обход кэша.


Обход «неудобных» шаблонов доступа к данным:


Выравнивание данных по границам, кратным 4, 8 и более байт. Обычно делается компилятором
именно потому, что на многих процессорах доступ, например, к 4-байтному целому в памяти
по адресу, не кратному 4, намного медленнее.


Использование нескольких имеющихся устройств одновременно (несколько ядер процессора/несколько
вычислительных устройств в ядре процессора/процессор и диск):


Многопоточная обработка. Эта тема слишком обширная чтобы пытаться охватить её здесь.
Использование специальных наборов команд процессора (MMX, SSE, …).
Расчёты на графических картах.
Обработка данных в одном потоке, буферизация и сохранение в другом потоке.


Обход латентности конвейера процессора:


Уменьшение количества условных переходов в принципе.
В частности – путём разворачивания циклов. Пример: для несложной обработки большого
массива данных 


вместо

for (int i = 0; i < n; i++) 
  process(a[i]);


может быть выгодно написать

int i, stopI = n - 4;
for (i = 0; i <= stopI; i += 4) {
  process(a[i]);
  process(a[i + 1]);
  process(a[i + 2]);
  process(a[i + 3]);
}
for ( ; i < n; i++) 
  process(a[i]);


(естественно, очень желательно, чтобы функции process была inline или просто одним
оператором)


Переупорядочивание операций. Подходит и для уменьшения зависимостей по данным и для
загрузки большего количества вычислительных устройств.
Совмещение итераций цикла. Аналогично предыдущему пункту – подходит для разных случаев.
Пример (тут тоже можно придумать что-нибудь получше): для обработки большого массива
данных 


вместо

for (int i = 0; i < n; i++) {
  b[i].x += deltaX;
  if (b[i].x < 0)
    b[i].x += 100;
  b[i].y *= b[i].x * y2;
}


-

int i, stopI = n - 2;
for (i = 0; i <= stopI; i += 2) {
  b[i].x += deltaX;
  if (b[i].x < 0)
    b[i].x += 100;
  b[i + 1].x += deltaX;   // Пока  b[i].y *= b[i].x * y2; ждёт выполнения процессором
условия и, возможно, += 100, мы начинаем обрабатывать следующий элемент
  if (b[i + 1].x < 0)
    b[i + 1].x += 100;
  b[i].y *= b[i].x * y2;
  b[i + 1].y *= b[i + 1].x * y2;
}
for ( ; i < n; i++) 
  …

    


Ответы

Ответ 1



Хорошая идея! Подождём ответов от специалистов по оптимизациям. Внесу свои 5 копеек: битовые трюки. Многие операции имеют неожиданно простую и эффективную реализацию с учётом особенностей двоичной записи чисел. Вот популярный сборник. Пример: для положительного числа v выражение (v & (v - 1)) == 0 определяет, является ли v степенью двойки. Ещё одним классическим трюком на грани между алгоритмическими и неалгоритмическими является быстрое вычисление 1/sqrt(x) из Quake.

Ответ 2



Внесу свои пять копеек. В многопоточных программах могут возникнуть проблемы с производительностью, когда потоки интенсивно выделяют/освобождают память. Это происходит из-за того, что стандартный malloc не умеет работать параллельно и просто делает lock на каждое выделение. С этим можно бороться по-разному, например выделяя большой кусок памяти для каждого потока, и используя его как пул. Но самый простой способ, это применить библиотеку tcmalloc, которая входит в gperttools. Самое приятное, что для ее использования ничего не надо менять в исходниках, нужно просто добавить флаг -ltcmalloc при линковке. На моей памяти простое добавление tcmalloc увеличивало производительность на 20-30% в одном проекте, связанном с алгоритмами на графе. UPD: Наваял демонстрацию: $ cat test.cc #include #include #include int main() { const int THREADS = 2; const int ITERATIONS = 50000000; std::vector threads; std::vector arr(THREADS, 0); for (int t = 0; t < THREADS; ++t) { threads.emplace_back([t, &arr]() { for (int i = 0; i < ITERATIONS; ++i) { std::unique_ptr ptr1(new int(i)); std::unique_ptr ptr2(new double(i)); arr[t] += *ptr1 + *ptr2; arr[t] %= ITERATIONS; } }); } for (std::thread& thread: threads) { thread.join(); } int sum = 0; for (int s: arr) { sum = (sum + s) % ITERATIONS; } return sum; } $ g++-4.7 --std=c++11 test.cc -O2 -pthread $ time ./a.out real 0m16.127s user 0m30.602s sys 0m0.172s $ g++-4.7 --std=c++11 test.cc -O2 -pthread -ltcmalloc $ time ./a.out real 0m8.743s user 0m16.417s sys 0m0.056s Как видно, даже на 2-х тредах tcmalloc ускорил программу почти в 2 раза.

Ответ 3



Вот такой примитвный. Просто транслирую с -DQUAKE и запускаю через time. avp@avp-xub11:~/src/codegoogle/smhasher$ grep CPU /proc/cpuinfo model name : Pentium(R) Dual-Core CPU E5400 @ 2.70GHz avp@avp-xub11:~/src/codegoogle/smhasher$ #include #include #include //float InvSqrt (float x); static inline float InvSqrt (float x){ float xhalf = 0.5f*x; int i = *(int*)&x; i = 0x5f3759df - (i>>1); x = *(float*)&i; x = x*(1.5f - xhalf*x*x); return x; } #if QUAKE #define WHO "QUAKE" #else #define WHO "sqrt() -lm " #endif int main() { int i; float x = 1.0; for (i = 0; i < 1000000000; i++) #if QUAKE x += InvSqrt(x); #else x += 1 / sqrt(x); #endif printf ("%s: x = %f\n", WHO, x); }

Ответ 4



К сожалению, у нас начинается флейм оптимизаторов-теоретиков и оптимизаторов-практиков (здесь и в вопросе-примере). Но т.к. я вспомнил практический пример в тему, я его всё-таки приведу :) . К вопросу о том, что всё, что не даёт лучшей оценки (O(n*log n) вместо O(n^2) и т.п.)- это баловство. Я тоже как-то, например, написал для каждой вставки в базу дополнительный select max(id)+1 ... Авто-инкремент там нельзя было сделать т.к. несколько процессов заливали данные в одну таблицу, но каждый - в своём диапазоне id, чтобы можно было по этим id в каждом диапазоне находить новые данные. Но суть не в этом. Суть в том, что когда код заработал, производительность была довольно грустной. Точно не помню, приведу очень примерные цифры ради отображения соотношений величин. Допустим, записывалось 50 элементов данных в секунду. При этом в процессе работы всех загрузчиков новых данных поступает 10 в секунду. Но когда загрузчики перезапускаются, им в сумме нужно загрузить 20000 элементов. Т.е. запас по прочности вроде как в 5 раз, но при рестарте надо ждать 6 минут. А код надо ещё тестировать и отлаживать. Было понятно, что select max(id)+1 это хрень, но избавление от него обещало прирост ну процентов 20 (что такого, быстренько в индексе пробежаться, тем более, он и так в памяти). И я точно помню, что мне казалось, что смысла нет. Тем не менее, после того, как мы немного подумали и я поправил эту и несколько подобных мелких проблем, производительность возросла раза в 3. И просто работать стало намного приятней! Не говоря о том, что я сэкономил себе много часов ожидания на имеющихся машинах (вполне нормальных по тем временам). Т.е. можно было ходить и плакаться, что мне надо машину на 1000$ дороже и сервер тоже, а можно было подумать-поработать пару дней. Upd: нашёл в одном вопросе (Книги по теме Concurrency и Parallel Programming) замечательный сборник статей. И в частности: приём переделки бинарных деревьев с тем, чтобы при спуске по дереву приходилось читать из памяти менее разбросанные данные: 1024CORES / RAM - не RAM, или Cache-Conscious Data Structures. Читается легко, всем рекомендую :)

Порядок уничтожения временных объектов

#cpp #g++ #language_lawyer


Недавно столкнулся с некоторой странностью при уничтожении временных объектов. Собственно,
вопрос следующий: почему объект под номером 2 удаляется раньше объекта под номером
1? Разве не должны выполняться деструкторы аргументов при выходе из области видимости,
то есть при возврате из функции? Почему вначале удаляется временный объект из функции
main, а затем аргумент foo? Почему не наоборот?

Код:

#include 
using std::clog;

struct A {
    static size_t counter;
    size_t me = counter++;
    A() { clog << "constructor A: " << me << "\n"; }
    A(const A& o) { clog << "copy A: " << me << "\n"; }
    A(A&& o) { clog << "move A: " << me << "\n"; }
    ~A() { clog << "destructor A: " << me << "\n"; }
};
size_t A::counter = 0;

A foo(A obj) {
    clog << "into foo\n";
    return obj;
}

int main() {
    A a;
    clog << "before foo\n";
    foo(a);
    clog << "between foo\n";
    A other = foo(a);
    clog << "after foo\n";
}


Вывод:

constructor A: 0
before foo
copy A: 1
into foo
move A: 2
destructor A: 2
destructor A: 1
between foo
copy A: 3
into foo
move A: 4
destructor A: 3
after foo
destructor A: 4
destructor A: 0


Компилятор GCC 5.1.1
    


Ответы

Ответ 1



Деструкторы вызываются в порядке обратном относительно вызывов конструкторов пл принципу стека LIFO (Last Input First Output). Сначало был создан объект с номером 1 посредством вызова конструктора копирования, так как исходный объект это lvalue . В стек также был занесен его деструктор. Затем внутри функции был вызван конструктор перемешения с номером 2 благодаря RVO (return value optimization). Этот конструктор вызван после конструктора параметра, а, следовательно, его деструктор помещен в стек перед деструктором объекта с номером 1. Таким образом последним помещенным в стек, объект с номером 2 удаляется первым. Согласно стандарту C++ (12.2 Temporary objects) 5....The destruction of a temporary whose lifetime is not extended by being bound to a reference is sequenced before the destruction of every temporary which is constructed earlier in the same full-expression. Переводя на русский язык, эта цитата из стандарта говорит о следующем: "Уничтожение временного объекта, чье время жизни не продлевается за счет привязки к ссылке, происходит перед уничтожением каждого временного объекта, который был создан ранее в том же самом полном выражении" Что касается второго предложения A other = foo(a); то временный объект строится непосредственно в объекте other, а потому и удаляется, когда сам этот объект удаляется. Если вы посмотрите на сообщения, которые сосответствуют этому предложению move A: 4 destructor A: 3 after foo destructor A: 4 то вы увидите, что благодаря RVO (return value optimization) локальный объект функции (ее параметр), который является lvalue, сразу же перемещается в объект other. На это указывает сообзения after foo destructor A: 4 То есть этот временный объект был построен в other и, соответственно удален после сообщения after foo когда функция main завершила свою работу.

Ответ 2



Почему у GCC такой порядок я честно говоря не знаю, у MSVC он другой - такой какой напрашивается. Но с моей точки зрения GCC имеет право на подобное поведение, т.к. стандарт говорит следующее: [5.2.2/4]: The lifetime of a parameter ends when the function in which it is defined returns. The initialization and destruction of each parameter occurs within the context of the calling function. Таким образом, параметр будет уничтожен уже после выполненного return в вызывающей функции. Но и возвращаемое значение будет уничтожено сразу по выходу из функции, т.к. выражение на этом заканчивается и все временные объекты из оного подлежат уничтожению. В принципе, возвращаемое значение "моложе" аргумента, а значит должно быть уничтожено до него. С другой стороны, деструктор возвращенного значения можно рассматривать как функцию, которая должна быть вызвана позже удаления аргумента. Таким образом можно считать, что стандарт несколько размыт в данном случае, а можно считать, что поведение GCC более соответствует стандарту. Предлагаю добавить в примеру всего пару строк, и всё станет ещё интереснее: #include using std::clog; struct A { static size_t counter; size_t me = counter++; int a; void foo() { clog << "foo me\n"; } A() { clog << "constructor A: " << me << "\n"; } A(const A& o) { clog << "copy A: " << me << "\n"; } A(A&& o) { clog << "move A: " << me << "\n"; } ~A() { clog << "destructor A: " << me << "\n"; } }; size_t A::counter = 0; A foo(A obj) { clog << "into foo\n"; return obj; } int main() { A a; clog << "before foo\n"; foo(a).foo(); clog << "between foo\n"; A other = foo(a); clog << "after foo\n"; } Вывод MSVC2013(Release): constructor A: 0 before foo copy A: 1 into foo move A: 2 destructor A: 1 foo me destructor A: 2 between foo copy A: 3 into foo move A: 4 destructor A: 3 after foo destructor A: 4 destructor A: 0 GCC/Clang: constructor A: 0 before foo copy A: 1 into foo move A: 2 foo me destructor A: 2 destructor A: 1 between foo copy A: 3 into foo move A: 4 destructor A: 3 after foo destructor A: 4 destructor A: 0 На мой взгляд логике стало ещё меньше и лично мне, вывод MSVC более логичен. Видимо разница вызвана тем, что для MSVC аргумент функции это объект локальный для функции, тогда как для GCC/Clang это объект принадлежащий full expression. А если совместить цитату из моего ответа, с цитатой из ответа Vlad from Moscow, тогда получается, что GCC/Clang всё делают правильно, а MSVC отходит от стандарта. Создал баг-репорт на connect, посмотрим, что ответят. Баг закрыли с формулировкой "by design" и привели ссылку, где указывается, что такое поведение допустимо. Таким образом мы имеем, что MSVC не содержит проблемы, но его поведение отличается от GCC/clang.

Ответ 3



Я подозреваю, что компилятор переписал функцию так: A foo(A obj) { clog << "into foo\n"; A result = std::move(obj); return result; } Clang, во всяком случае, выдает с ней такой же вывод. Тогда если забыть об RVO, то все выглядит логично. Но с RVO все равно у меня в голове не клеется. Скорее всего компилятор очень искусно притворяется, что не делает RVO.

Как программно узнать, что устройство работает в режиме Wi-Fi точки доступа?

#java #android #wifi


Как можно средствами Java узнать, что телефон находиться в режиме "точка доступа"?

Мне необходимо узнать, раздаёт ли телефон Wi-Fi / подключен ли к нему.

Вот код на проверку подключения к Wi-Fi:

public boolean isWiFiOn() {
    final WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
    if(wifi != null)
        switch(wifi.getWifiState()) {
            case(WifiManager.WIFI_STATE_DISABLED):
            case(WifiManager.WIFI_STATE_DISABLING):
                return false;
            default:
                return true;
        }
    return false;
}


Но этот код возвращает false, если телефон в режиме точки доступа.

Как в таком случае узнать, раздаёт ли он Wi-Fi?
    


Ответы

Ответ 1



Официально узнать нельзя, но Android на то и "андроид", что много чего можно сделать при помощи хаков: Есть спрятанный @hide метод getWifiApState: Method method = wifiManager.getClass().getDeclaredMethod("getWifiApState"); method.setAccessible(true); int actualState = (Integer) method.invoke(wifiManager, (Object[]) null); Далее actualState сравниваем с такими константами: public static int WIFI_AP_STATE_DISABLING = 10; //выключается public static int WIFI_AP_STATE_DISABLED = 11; //выключен public static int WIFI_AP_STATE_ENABLING = 12; //включается public static int WIFI_AP_STATE_ENABLED = 13; //включен public static int WIFI_AP_STATE_FAILED = 14; //сломалсо UPD: ссылка на метод в исходниках:

Что такое Unicode и как с ним связана UTF-8

#unicode


Со страницей википедии про Unicode ознакомился, но так и не понял, хотя там и написано
что это стандарт кодирования символов

Насколько я знаю то Unicode представлен следующим образом


  0x00000000 — 0x0010F800


Есть такое утверждение, что UTF-16 = Unicode, так ли это?

UTF-16 представлен как 256*256 = 65 536 (без суррогатных пар), с суррогатными парами
формула такая 2^20+2^16−2048 - тут не ясно как такая формула получилась, кто сведущ
объясните (без суррогатных пар все ясно)

UTF-8 представлен следующим образом


  4 байта (то что используется)
  
  0x00000000 — 0x001FFFFF
  
  6 байта (то что не используется)
  
  0x00000000 — 0x7FFFFFFF


Тут как бы назревает вопрос а как мы можем переводить из UTF-8 в Unicode если Unicode
кодирует в 2 раза меньше символов?

Что такое Unicode и зачем в него переводить допустим из той же самой UTF-8?

P.S Каша в голове, запутался уже X_X, помогите проявить ясность в голове
    


Ответы

Ответ 1



Резюмируя написанное в комментариях и чате. Примечание: данный ответ не претендует на строгую спецификацию, а является объяснением «на пальцах» для улучшения понимания и может содержать неточности, а для разработки программ лучше читать не SO и даже не Википедию, а непосредственно сам стандарт. В контексте вопроса Unicode — это просто табличка символов и закреплённых за ними целых чисел (не каких-либо байт, а обычных человеческих чисел). (А ещё юникод описывает обработку символов и их преобразования друг в друга, но вопрос не про это.) Кусочек этой таблички: Эта табличка не указывает, как именно эти числа переводить в байты, которые можно было бы сохранить в компьютере. Но, чтобы хранить юникод в компьютере, кто-то должен указать, как их всё-таки переводить! Возьмём числа из этой таблички символов и запихнём их в четыре байта так, чтобы четыре байта представляли беззнаковое целое число (unsigned int, uint32). То есть, например, из кода буквы «Я» 42F16 получаем байты 00 00 04 2F. Таким образом мы получили простейшую кодировку UTF-32 (UTF-32-BE1, UCS-4). Если интерпретировать эти полученные четыре байта как беззнаковое целое число, то мы получим номер символа в табличке Unicode. С уточнением, что мы используем uint32, можно для себя считать, что UTF-32 = Unicode: каждое число кодируется-декодируется как есть без каких-либо преобразований. Если мы возьмём числа из таблички и запихнём их в два байта, представляющие беззнаковое целое число (unsigned short, uint16), то мы получили бы первую версию Юникода, которая была в 1991 году. Тогда число символов было ограничено 65536, и все их коды можно было легко представить двумя байтами без дополнительных преобразований. Но потом решили, что 65 тысяч это как-то мало, и увеличили максимальное количество символов до миллиона. Но ведь миллион в два байта уже никак не запихнёшь, и нужно взять больше байт на символ. Но так как уже успели появиться программы, рассчитывающие на эти самые два байта (например, в Java или Windows NT длина одного символа до сих пор 2 байта), то для сохранения хоть какой-то обратной совместимости из этих двух байт выдрали диапазон D80016..DFFF16 и сказали, что это суррогатные пары, занимающие по четыре байта и обрабатывающиеся по особому алгоритму для символов с кодом 1000016 и больше. И назвали всё это кодировкой UTF-16. Таким образом, в UTF-16 числа из таблички юникода, попадающие в диапазоны 000016..D7FF16 и E00016..FFFF16, записываются в два байта как есть, а символы с кодами 1000016 и больше записываются в виде суррогатных пар с использованием диапазона D80016..DFFF16 и занимают четыре байта. Так старые приложения, сделанные под первую двухбайтовую версию Юникода, смогли продолжить и дальше с ним работать, если не используются суррогатные пары. Таким образом та же буква «Я» (код 42F16) представляется в UTF-16 (UTF-16-BE) как 04 2F, а символ «🔒» с кодом 1F51216, не влезающим в два байта, по алгоритму преобразуется в четыре байта D8 3D DD 12. Из-за этих самых суррогатных пар с кучей преобразований UTF-16 ≠ Unicode. UTF-8 была сделана для совместимости с ASCII: в ней коды символов от 0 до 7F16 записываются в один байт как есть, в итоге выдавая этот самый ASCII, а всё остальное кодируется по алгоритмам ещё более хитрым, чем в UTF-16, поэтому UTF-8 ≠ Unicode тоже. Технически UTF-8 позволяет закодировать числа аж до двух миллиардов, однако Unicode ограничен миллионом символов, и стандартом установлено, что кодировать в UTF-8 числа, не входящие в допустимый диапазон Unicode, запрещено. Поэтому проблемы перевода из UTF-8 в Unicode чисел, не входящих в Unicode, просто нет: хорошо сделанное приложение в таких случаях выкинет ошибку или заменит всё недопустимое символом �. В Notepad и Notepad++ можно наблюдать кодировку, названную «Unicode», но на самом деле это UTF-16-LE с BOM1. (клик для увеличения) Самой распространённой кодировкой вроде как является UTF-8. 1 — числа, занимающие более одного байта, можно записывать с разным порядком байт: например, число 259 можно записать как 01 03 (big endian, BE) или как 03 01 (little endian, LE). То же самое применимо к символам в кодировках UTF-16, UTF-32 и некоторым другим (но не UTF-8). Вышеупомянутый 🔒 кодируется в UTF-16-LE неё как 3D D8 12 DD — в то время как в UTF-16-BE это будет D8 3D DD 12. BOM — это специальный символ FEFF16 в начале текста, который позволяет определить этот самый порядок байт — в big endian он пишется как FE FF, а в little endian как FF FE, а использование символа FFFE16 запрещено, что и позволяет определить порядок байт.