Тема: допоможіть початківцю
ннн
Ви не увійшли. Будь ласка, увійдіть або зареєструйтесь.
Ласкаво просимо вас на україномовний форум з програмування, веб-дизайну, 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 ?
Для відправлення відповіді ви повинні увійти або зареєструватися