Решение P-A частично работает для меня. Подробно мои выводы ниже:
1) Первый фрагмент кода неверен, см. Ниже:
<activity
...
<intent-filter>
==> <action android:name="android.intent.action.MAIN" /> <== This line shouldn't be deleted, otherwise will have compile error
<category android:name="android.intent.category.LAUNCHER" /> //DELETE THIS LINE
</intent-filter>
</activity>
2) Должен использовать следующий код для отключения всех значков до включения другого, иначе он добавит новый значок вместо его замены.
getPackageManager().setComponentEnabledSetting(
getComponentName(), PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
НО, если вы используете код выше, то ярлык на главном экране будет удален! И он не будет автоматически добавлен обратно. Возможно, вы сможете программно добавить значок обратно, но он, вероятно, не останется в том же положении, что и раньше.
3) Обратите внимание, что значок не будет изменен немедленно, это может занять несколько секунд. Если вы нажмете его сразу после изменения, вы можете получить сообщение об ошибке: «Приложение не установлено».
Итак, IMHO это решение подходит только для изменения значка только в приложении запуска, а не для быстрого доступа ( т.е. значок на рабочем столе)
Когда вы ссылаетесь на переменную по имени, вы всегда получаете lvalue. Исключений из этого правила нет, хотя обратите внимание, что это не относится к препроцессорным макросам, счетчикам или параметрам шаблона непигового типа, ни одна из которых не является переменными в обычном смысле.
Я утверждаю, что хотя это поведение сначала кажется не имеющим смысла, когда вы считаете его более осторожным, оно имеет смысл и является правильным поведением. Во-первых, следует заметить, что категория значений явно является свойством выражений , , а не самих объектов. Это очевидно, так как std::move
никогда не создает новый объект, а просто создает выражение rvalue, относящееся к данному объекту. Тогда мы должны понимать, что:
T{}
в одном выражении отличается от T{}
в более позднем выражении, оба создают анонимные объекты, но оба они различны, поэтому последний не имеет доступа к тому же объекту, что и первый.) Таким образом, категория значений выражения, ссылающегося на объект, является relative; зависит от конкретного выражения и области видимости. std::move
сигнализирует о своем намерении не получать доступ к значению объекта снова в той же области действия, что позволяет вызываемой функции перемещать свое значение из этого объекта. Однако, когда вызываемая функция обращается к имени ссылки rvalue, это значение является постоянным во время вызова функции; функция может перемещать значение из этого объекта в любой точке или вообще не работать, но, во всяком случае, он, вероятно, получит доступ к нему в теле, который после инициализации параметров.
В этом примере :
void f(Foo&& foo) { /* use foo */ }
void g() {
Foo foo;
f(std::move(foo));
}
, хотя std::move(foo)
в g
и параметр foo
в вызываемой ссылке относятся к одному и тому же объекту, это значение объекта исчезнет на точки std::move
в g
, тогда как в f
ожидается, что значение этого объекта будет доступно через foo
, возможно, несколько раз до конца f
.
A аналогичная ситуация существует при вызове ref-квалифицированных функций-членов.
struct Foo {
void f() &;
void f() &&;
void g() && {
f(); // calls lvalue-qualified f
}
};
void h() {
Foo().g();
}
Здесь значение Foo()
вот-вот исчезнет из h()
; он не будет доступен после полного выражения . Однако в теле Foo::g()
он остается постоянным до конца g()
; *this
надежно обращается к значению одного и того же объекта. Поэтому естественно, что когда g()
вызывает f()
, он должен вызывать перегрузку, ожидающую lvalue, и f()
не должен красть значение *this*
из g()
, так как g()
может все еще хотеть получить к нему доступ .
В g()
t
- именованная переменная. Все именованные переменные являются lvalues. Если T
является типом шаблона, вы можете перенаправить переменную на f()
с помощью std::forward
. Это вызовет f()
с тем же типом, который был передан в g()
template<typename T>
g(T&& t) { f(std::forward<T>(t));}
Если T
не тип шаблона, а просто тип, вы можете использовать std::move
g(T&& t) { f(std:move(t)); }
std::move
, то зачем вообще использовать forward
?
– Saurav Sahu
22 August 2017 в 15:41
То, что автоматически обрабатывается как rvalues, это вещи без имен, а вещи, которые (очень скоро) не будут иметь имени (в случае возвращаемого значения).
T&& t
имеет имя, это t
.
Причина, по которой rvalues - это то, что ссылается на них после , что точка использования почти невозможна.
T&&
является ссылкой типа rvalue. Ссылка rvalue может связываться только с rvalue (без участия static_cast
), но в остальном это значение lvalue типа rvalue.
Тот факт, что он относится к типу rvalue, имеет значение только во время его построения , и если вы сделаете decltype(variable_name)
. В противном случае это просто другое значение ссылочного типа.
std::move(t)
выполняет return static_cast<T&&>(t);
и возвращает ссылку rvalue.
Правила, которые регулируют это, написаны стандартными в стандарте C ++. Копия / вставка из них не все так полезно, потому что их не так просто понять.
Первое общее правило: вы получаете неявный ход (aka, параметр, который привязывается к rvalue ссылочный аргумент), когда вы возвращаете именованное значение из функции или когда значение не имеет имени или когда функция явно возвращает ссылку rvalue.
Во-вторых, только ссылки rvalue и const&
могут связываться на rvalues.
В-третьих, расширение жизненного цикла ссылки на временные значения происходит, когда напрямую связано с ссылкой вне конструктора. (поскольку только ссылки rvalue и const&
могут напрямую привязываться к временному, это относится только к ним)
Forth, T&&
не всегда является ссылкой rvalue. Если T
имеет тип X&
или X const&
, тогда свертывание ссылки сворачивает T&&
в X&
или X const&
.
Наконец, T&&
в контексте вывода типа выводит T
в качестве X
, X&
, X const&
или X const&&
в зависимости от типа аргумента и, следовательно, может выступать в качестве «ссылки пересылки».