Причудливый вывод: почему этот код должен давать какой-либо осмысленный вывод, не говоря уже об этом?

Я не уверен, как даже сформулировать свой вопрос, но вот...

Итак, у меня есть этот класс, для которого operator[] имеет пустое тело (еще не реализовано). Тем не менее, когда я вызываю его из main(), он выдает результат. Более того, вывод — это именно то, что было назначено ему в предыдущей строке.

EDIT: я добавил частный атрибут с именем emptyValue и инициализировал его значением TipVrijednosti() в конструкторе класса.

Вот пример:

  template<typename TipKljuca, typename TipVrijednosti>
    class BinStabloMapa : public Mapa<TipKljuca, TipVrijednosti>
    {
            .
            .
        TipVrijednosti &operator[] (const TipKljuca &kljuc) {
            return emptyValue;
        }
        const TipVrijednosti &operator[] (const TipKljuca &kljuc) const {
            return emptyValue;
        }
            .
            .
    }

    int main()
    {
        BinStabloMapa<int, int> m;
        m[100] = 200;
        cout << m[100] << endl;
        return 0;
    }

    OUTPUT: 200

Может ли кто-нибудь сказать мне, почему я это происходит?


person irfanka    schedule 26.12.2013    source источник
comment
Вы могли бы также использовать английский язык в своем фрагменте кода: P   -  person P0W    schedule 26.12.2013
comment
Скорее всего, проблема со сборкой или проблема при создании вопроса из реального кода. @ P0W: Совершенно не согласен, в вопросах должен быть реальный код, который дает сбой, я очень устал от людей, массирующих код с целью задать и скрыть проблему в то же время. Я бы взял настоящий код на любом языке, прежде чем неправильный код на английском в любой день.   -  person David Rodríguez - dribeas    schedule 26.12.2013
comment
Что возвращает функция TipVrijednosti()?   -  person drescherjm    schedule 26.12.2013
comment
Какой причудливый компилятор используется?   -  person SChepurin    schedule 26.12.2013
comment
@DavidRodríguez-dribeas Я согласен, но похоже, что это SSCCE, который мог быть оформлен на всем известном языке. А еще оказывается, что вы знаете этот самый язык. Но это все фигня для того, кто никогда не сталкивался с таким языком. (Я знаю, что это не имеет ничего общего с ответами, но удобочитаемость имеет значение). Ваше здоровье !   -  person P0W    schedule 26.12.2013
comment
@ P0W: Чтобы было ясно: я вообще не знаю этого языка. Если бы мне пришлось угадывать, я бы сказал, что это похоже на польский или похожий, но я не понимаю ни одного из идентификаторов, но вам не нужно понимать, что означает TipKljuca, чтобы знать, что это ключ в какую-то форму карты (я бы использовал K в качестве аргумента шаблона, который не так уж и близок к английскому языку — выводится из аргумента шаблона и типа аргумента в operator[]).   -  person David Rodríguez - dribeas    schedule 26.12.2013


Ответы (3)


У вас неопределенное поведение, потому что вы ничего не возвращаете из функции, которая имеет тип возвращаемого значения, отличный от void.

§6.6.3:

Вытекание конца функции эквивалентно возврату без значения; это приводит к неопределенному поведению функции, возвращающей значение.

§1.3.24:

неопределенное поведение
поведение, для которого настоящий международный стандарт не устанавливает требований

person Joseph Mansfield    schedule 26.12.2013
comment
Итак, я добавил оператор return, и ничего не изменилось. - person irfanka; 26.12.2013
comment
@IrfanKahvedzic Что такое emptyValue? - person Joseph Mansfield; 26.12.2013
comment
@IrfanKahvedzic Если emptyValue является переменной-членом, теперь, как вы, кажется, указываете, вы больше не находитесь в стране UB. Поскольку operator [] возвращает ссылку на emptyValue, строка m[100] = 200; фактически присваивается ему. - person Sean Cline; 26.12.2013
comment
Что ж, поскольку это общий класс, я не могу просто вернуть 0, потому что TipVrijednosti не обязательно должен быть целым числом. Поэтому я вернул TipVrijednosti(), который является вызовом его конструктора. (emptyValue=TipVrijednosti()) - person irfanka; 26.12.2013
comment
@SeanCline да, я так и думал, но не был полностью уверен. Спасибо. - person irfanka; 26.12.2013

Не такая уж большая головоломка. Ваш operator [] возвращает ссылку на некоторую переменную данных с именем emptyValue.

            m[100] = 200;

эквивалентно

            m.emptyValue = 200;

Затем вы пишете cout ‹‹ m[100];

что похоже на

            cout << m.emptyValue;

Примечание: индекс «100» не имеет значения.

person Michael J    schedule 26.12.2013
comment
Примечание: индекс «100» не имеет значения. +1 - person drescherjm; 26.12.2013

С этим ничего не поделаешь:

#include <iostream>
using namespace std;
template<typename TipKljuca, typename TipVrijednosti>
class BinStabloMapa /* : public Mapa<TipKljuca, TipVrijednosti> */ 
//comment inheritance to make it compile, not relevant to the problem
{
    //C++11 syntax, not relevant either
    TipVrijednosti emptyValue=TipVrijednosti();
    public:    
    TipVrijednosti &operator[] (const TipKljuca &kljuc) {
        return emptyValue;
    }
    const TipVrijednosti &operator[] (const TipKljuca &kljuc) const {
        return emptyValue;
    }


};

int main()
{
    BinStabloMapa<int, int> m;
    m[100] = 200; //calls no const operator[], thus emptyValue is changed 
    cout << m[100] << endl; //calls const operator[], thus emptyValue is return
    return 0;
}
person Davidbrcz    schedule 26.12.2013