Тема: допоможіть початківцю
ннн
Ви не увійшли. Будь ласка, увійдіть або зареєструйтесь.
Ласкаво просимо вас на україномовний форум з програмування, веб-дизайну, SEO та всього пов'язаного з інтернетом та комп'ютерами.
Будемо вдячні, якщо ви поділитись посиланням на Replace.org.ua на інших ресурсах.
Для того щоб створювати теми та надсилати повідомлення вам потрібно Зареєструватись.
Український форум програмістів → C++ → допоможіть початківцю
Для відправлення відповіді ви повинні увійти або зареєструватися
ннн
Заголовок беззмістовний.
Помилку ми не допоможемо виправити, оскільки ви не написали, що ви хочете зробити і що у вас за помилка. Наприклад, компілятор може повідомляти, що у вас закінчилося місце на диску - як ми це побачимо? А якщо ми навіть здогадаємося, що у вас за помилка - як ми напишемо, що треба, якщо ви не сказали, що має робити програма?
Матеріалів про вказівники (чи показчики, але не поїнтери і не указатєлі) купа. Що ви вже прочитали?
Ну і дуже не раджу лізти в ООП до того, як розберетеся із вказівниками.
Можете оцінити код і сказати в чому заключаєтьсяся моя криворукість, і як робити правельніше (помилку я знайшов)
#include <iostream>
using namespace::std;
class Address{
private:
int index;
char *country;
char *city;
char *street;
int house;
public:
Address(){}
Address(int initialIndex, char *initialCountry, char *initialCity, char *initialStreet, int initialHouse){
index = initialIndex;
country = initialCountry;
city = initialCity;
street = initialStreet;
house = initialHouse;
}
~Address(){
delete [] country;
delete [] city;
delete [] street;
}
int getIndex(){
return index;
}
char* getCountry(){
return country;
}
char* getCity(){
return city;
}
char* getStreet(){
return street;
}
int getHouse(){
return house;
}
void printAddress(){
cout << getIndex() << " " << getCountry() << " " << getCity() << " " << getStreet() << " " << getHouse() << "\n";
}
void setIndex(int newIndex){
index = newIndex;
}
void setCountry(char *newCountry){
country = newCountry;
}
void setCity(char *newCity){
city = newCity;
}
void setStreet(char *newStreet){
street = newStreet;
}
void setHouse(int newHouse){
house = newHouse;
}
void setAddress(int newIndex, char *newCountry, char *newCity, char *newStreet, int newHouse){
index = newIndex;
country = newCountry;
city = newCity;
street = newStreet;
house = newHouse;
}
};
int main(){
Address *address = new Address[2];
address[0].setAddress(4300, "Ukraine", "Kiev", "Kirovskaya", 99);
address[1].setAddress(7400, "Ukraine", "Kiev", "Mitnutska", 12);
address[0].printAddress();
address[1].printAddress();
}
Якщо деталізувати попередню відповідь - основна помилка у вас у тому, що ваші поля класу вказують на пам'ять яку ви не контролюєте. А ви навіть не перевіряєте їх валідність. Тож наприклад цілком валідний код
//far far away
std::string street, country, city;
...
//ups!
address[1].setAddress(7400, country.c_str(), city.c_str(),street.c_str(), 12);
на пустому місці приведе до проблем.
Тому (якщо у вас немає нууууудуже поважної причини цього не робити) слід дотримуватися:
1) Завжди використовуйте std::string
2) Якщо не маєте інших причин - передавайте за просилянням а не за вказівником
3) Якщо використовуєте вказівник - необхідно перевіряти його валідність.
P.S. Для індексу та номера будинку (а також квартир, блоків та ін.) використовують строки.
Вам необхідно розібратися що таке С а що таке С++.
#include <iostream>
using namespace::std;
cout << getIndex() << " " << getCountry() << " " << getCity() << " " << getStreet() << " " << getHouse() << "\n";
Це С++, все інше у вас на С
(У С++ не рекомендується використовувати вказівники та вручну керувати пам'яттю)
Якщо доповнити попередні відповіді, то
Баг #1
"Kyiv" а не "Kiev"
Менш важлива проблема:
address[0].setAddress(4300, "Ukraine", "Kiev", "Kirovskaya", 99); {0}
{1}
address[0].printAddress(); {2}
В точці {0} ви створили тимчасові змінні, які передаються у функцію setAddress як rvalue.
Проблема rvalue в тому, що як тільки ви вийшли з функції setAddress (точка {1}), вони одразу ж видаляються з памяті!
Тому на момент виклику функції printAddress {2}, ваші вказівники вказуть на мусор!
Як правильно написати залежить на чому це треба зробити, на С чи С++
lvalue це те що має ім'я. А маючи ім'я, йому можна змінювати значення.
lvalue це те що має ім'я. А маючи ім'я, йому можна змінювати значення.
ви явно перечитались вумних книжок на тему "шо нівякомуразі(R) ніззя робити в с++". того ви знаєте такі вумні слова як lvalue і rvalue, а от по суті нопейсали фігню вибачте на слові.
ось тут нопейсале:
В точці {0} ви створили тимчасові змінні, які передаються у функцію setAddress як rvalue.
Проблема rvalue в тому, що як тільки ви вийшли з функції setAddress (точка {1}), вони одразу ж видаляються з памяті!
Тому на момент виклику функції printAddress {2}, ваші вказівники вказуть на мусор!Як правильно написати залежить на чому це треба зробити, на С чи С++
От подумайте, шо саме там "одразу видаляється з пам'яти"?
я як безнадійний сішник який ніасіліл с++ розумію, шо то вказівники на рядки. самі рядки - то глобальні безіменні константи, які лежатимуть спокійно в якій небудь RO секції, і звичайно, нікуди не будуть видалені. А вказівники на них які насправді передаються тій функції - то її аргументи, локальні для неї змінні власне, і вона копіює їхні значення в приватні для класу поля, і нічого не губиться, коли функція вертається і її стек зчищається разом з цими аргументами.
то глобальні безіменні константи, які лежатимуть спокійно в якій небудь RO секції, і звичайно, нікуди не будуть видалені.
дякую, поржав
Я уже все пояснив. Можу хіба що спростити код, щоб було легше зрозуміти
Як на вашу думку, що буде виведено?
Сподіваюсь на 2 відповіді, спочатку без компіляції, а потім після компіляції
#include <iostream>
const int& max(const int& a, const int& b)
{
return (a > b) ? a : b;
}
int main()
{
const int lvalue1 = 100;
const int lvalue2 = 50;
const int& max1 = max(lvalue1, lvalue2);
const int& max2 = max(lvalue1, 30);
const int& max3 = max(lvalue1, 130);
const int& max4 = max(200, 230);
std::cout << max1 << '\n';
std::cout << max2 << '\n';
std::cout << max3 << '\n';
std::cout << max4 << '\n';
return 0;
}
Рядковий літерал це lvalue; всі інші літерали це prvalues.
Наслідок спроби зміни рядкового літералу невизначений.
Ніхто не може видалити рядковий літерал. Хоча такий літерал може лежати і не в RO секції, але зазвичай таки там.
Yola, модифікував задачу для вас:
#include <iostream>
const std::string& f(const std::string& a)
{
return a;
}
int main()
{
const std::string lvalue = "lvalue";
const std::string& f_lvalue = f(lvalue);
const std::string& f_rvalue = f("rvalue");
std::cout << "lvalue: " << f_lvalue << '\n';
std::cout << "rvalue: " << f_rvalue << '\n';
return 0;
}
Отут ви можете створити тимчасовий об'єкт типу string, якщо ви його створюєте, то ви повертаєте посилання на локальну змінну:
const std::string& f(const std::string& a)
Тут нормально, ви передаєте string і відповідно тимчасова змінна не створюється:
const std::string lvalue = "lvalue";
const std::string& f_lvalue = f(lvalue);
А тут ви створюєте тимчасовий об'єкт:
const std::string& f_rvalue = f("rvalue");
А "rvalue" - це lvalue, стандарт каже.
output яким буде?
У мене вийшло ось, що:
lvalue: lvalue
rvalue:
Але, гадаю, що це
const std::string& f(const std::string& a) { return a; }
невизначена поведінка, тому покладатись на такий вивід не можна.
Щоб уникнути невизначеної поведінки треба писати так (без посилання на локальну змінну):
const std::string f(const std::string& a) { return a; }
У мене вийшло ось, що:
lvalue: lvalue
rvalue:
чому rvalue не роздрукувався? він жеж лежить в глобальній секції для тимчасових змінних!! значить ініціалізується на старті програми та має жити до її завершення!!
без посилання на локальну змінну
а не локальна зміна функції f(), це тимчасова зміна функції main(), нарізана на стеці, i як тільки завершився виклик f(), вона видалилась. Жодної глобальної секції для тимчасових обєктів не існує!
Пане hesting, ви неуважно читали мої попередні повідомлення. Гляньте №15. У випадку коли ви передаєте const char* то створюється тимчасова змінна і ви повертаєте посилання на неї. А ця змінне перестає бути валідною там де закінчується вираз:
const std::string& f_rvalue = f("rvalue");
Тобто далі посилання на цю тимчасову змінну - невизначена поведінка.
повідомлення #15 не зовсім чітко формулює вашу позицію
А тут ви створюєте тимчасовий об'єкт:
const std::string& f_rvalue = f("rvalue");
А "rvalue" - це lvalue, стандарт каже.
поясніть детальніше, чому "rvalue" це по вашому lvalue ?
Для відправлення відповіді ви повинні увійти або зареєструватися