Podivné chování std :: cout a operátor <<

hlasů
1

Narazil jsem na něco divné dnes, a mě napadlo, jestli někdo z vás tady mohl vysvětlit, co se děje ...

Zde je ukázka:

#include <iostream>
#include <cassert>
using namespace std;

#define REQUIRE_STRING(s)           assert(s != 0)
#define REQUIRE_STRING_LEN(s, n)    assert(s != 0 || n == 0)

class String {
public:
        String(const char *str, size_t len) : __data(__construct(str, len)), __len(len) {}
        ~String() { __destroy(__data); }

        const char *toString() const {
            return const_cast<const char *>(__data);
        }

        String &toUpper() {
            REQUIRE_STRING_LEN(__data, __len);
            char *it = __data;
            while(it < __data + __len) {
                if(*it >= 'a' && *it <= 'z')
                    *it -= 32;
                ++it;
            }
            return *this;
        }

        String &toLower() {
            REQUIRE_STRING_LEN(__data, __len);
            char *it = __data;
            while(it < __data + __len) {
                if(*it >= 'A' && *it <= 'Z')
                    *it += 32;
                ++it;
            }
            return *this;
        }

private:
        char *__data;
        size_t __len;

protected:
        static char *__construct(const char *str, size_t len) {
            REQUIRE_STRING_LEN(str, len);
            char *data = new char[len];
            std::copy(str, str + len, data);
            return data;
        }

        static void __destroy(char *data) {
            REQUIRE_STRING(data);
            delete[] data;
        }
};

int main() {
    String s(Hello world!, __builtin_strlen(Hello world!));

    cout << s.toLower().toString() << endl;
    cout << s.toUpper().toString() << endl;

    cout << s.toLower().toString() << endl << s.toUpper().toString() << endl;

    return 0;
}

Teď jsem čekal výstup bude:

hello world!
HELLO WORLD!
hello world!
HELLO WORLD!

ale místo toho jsem dostal toto:

hello world!
HELLO WORLD!
hello world!
hello world!

Nemůžu pochopit, proč druhá toUpperneměla žádný vliv.

Položena 22/04/2010 v 18:34
zdroj uživatelem
V jiných jazycích...                            


1 odpovědí

hlasů
20

Je to všechno kvůli kódu

cout << s.toLower().toString() << endl << s.toUpper().toString() << endl;

a jakým způsobem toLowera toUpperjsou implementovány. Následující kód by měl fungovat podle očekávání

cout << s.toLower().toString() << endl;
cout << s.toUpper().toString() << endl;

Problém je, že toLoweri toUppernevytvářejí nový objekt, ale upravit existující objekt. A když voláte několik pozměňujících metod v jednom bloku a předat tento objekt někde jako argumentu, chování není definováno.

EDIT: To je podobné jako populární otázku, co by bylo výsledkem

int i = 5;
i += ++i + i++;

Správná odpověď je zde stejná: nedefinovaný. Google vám může pro „sekvence bodů“ v jazyce C ++ pro hlubší vysvětlení.

Odpovězeno 22/04/2010 v 18:39
zdroj uživatelem

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more