#include "iostream"
int main()
{
std::string s = "abc";
for ( const auto& item : s ) {
std::cout << &item << std::endl;
}
}
результат азбука До нашей эры с
#include "iostream"
int main()
{
std::string s = "abc";
for ( const auto item : s ) {
std::cout << &item << std::endl;
}
}
затем выведите странные слова, но первое слово правильное
в чем разница между двумя приведенными выше кодовыми блоками?
@HolyBlackCat, это адрес персонажа в строке
В первом случае вы печатаете указатель char*, указывающий на блок символов, управляемый s; этот блок символов завершается нулем. Во втором случае у вас есть временная переменная char, вы берете адрес этой переменной и обрабатываете его как указатель на строку с завершающим нулем, но это не так. Затем программа демонстрирует неопределенное поведение из-за переполнения буфера.
А знаете ли вы, что происходит, когда вы передаете адрес символа в << выходного потока?
Да, так что вы ожидаете, что он напечатает символ или адрес?
@Pepijn Kramer, ожидайте, что будет напечатано то же самое с первым блоком
Итак, даже если и const auto& item, и &item используют &, то & делает разные вещи. const auto& item устанавливает константную ссылку на элемент, и для остальной части кода она будет «выглядеть» как этот элемент. Во втором случае & возвращает адрес товара. Так что это может быть немного сложно выучить, но значение & зависит от контекста.
@Sam Варшавчик, он будет печатать символы адреса и рядом с ним, пока не коснется nul-terminated
Ага, а const auto item — персонаж-одиночка, рядом с ним ничего нет.
Во втором примере вы передаете адрес переменной item в operator<<, а не адрес чего-либо в строке. Это происходит только в первом примере.
Правильно, так что именно в наблюдаемых результатах вам непонятно?
static_cast<void const*>(&item) чтобы распечатать адрес товара. Предположим, что это ваше намерение.
@Sam Varshavchik , код второго блока item это копия персонажа , а не символ s , меня это смутило , теперь я понял





& можно использовать для разных целей.
0xF0 & 0x0F --> & побитовое иtrue && false --> && - логическое/логическое иint var{0}; &var; --> & является оператором адреса и возвращает адрес объекта или указатель на объект, на котором вы его используете.int& sameVar{var}; --> & создает ссылку с именем sameVar, которая привязана к var. С его помощью вы можете получить доступ к var и изменить его, как если бы у вас был «настоящий» var.Вы используете оператор адреса в каждом операторе std::cout, который возвращает char* (указатель на char). При печати чего-то вроде int* с std::cout он выводит свой адрес, который может выглядеть так: 000000734F9CF8D4. Однако char*s — это нечто особенное в языках C и C++, поскольку они используются для представления c-строк. std::cout будет печатать все следующие char, начиная с адреса памяти, который вы ему дали, пока не встретится с \0, который является ограничителем NUL для c-строк.
В первом блоке кода вы используете
for ( const auto& item : s )
// which is the same as
for ( const char& item : s)
// you could imagine the loop like this:
for (int i{ 0 }; i < s.size(); i++) {
std::cout << &s[i] << std::endl;
}
Это означает, что каждый item ссылается на char в вашем std::string s. В первой итерации item == s[0] будет правдой, а также &item == &s[0] будет правдой. В следующих итерациях эти два утверждения по-прежнему будут истинными, если вы будете увеличивать индекс на каждой итерации. Это означает, что вы будете печатать c-строку на каждой итерации, но продвигаясь вперед к первой char, вы печатаете каждый раз. Поэтому вы получаете вывод:
abc
bc
c
Во втором блоке кода вы используете
for ( const auto item : s )
// which is the same as
for ( const char item : s)
// you could imagine the loop like this:
for (int i{ 0 }; i < s.size(); i++) {
char copy{ s[i] };
std::cout << © << std::endl;
}
Это означает, что каждый item сейчас является копией char в s. item == s[0] по-прежнему будет истинным, но &item == &s[0] не будет истинным, поскольку это разные объекты. То же самое касается следующих итераций и увеличения индекса. Поскольку вы на самом деле не знаете адрес item здесь и то, что следует за ним, вы не должны печатать его таким образом. Поскольку std::cout будет продолжать печатать char, пока не достигнет \0, вы получите случайный мусор.
Вы знаете, что означает
&?