стд::строка х(х);

std::string x(x);

Это очень сильно падает на моем компиляторе. Означает ли это, что я должен тестировать this != &that в своих собственных конструкторах копирования, или я могу предположить, что ни один клиент никогда не будет таким глупым?


person fredoverflow    schedule 27.03.2010    source источник
comment
Вы имеете в виду крах полученной программы или крах самого компилятора?   -  person Marcelo Cantos    schedule 27.03.2010
comment
В конструкторе копирования это не нужно, но вы должны проверить это в операторе присваивания.   -  person Björn Pollex    schedule 27.03.2010
comment
Полученная программа аварийно завершает работу во время выполнения.   -  person fredoverflow    schedule 27.03.2010
comment
Тогда подойдет любой из предложенных ответов.   -  person Marcelo Cantos    schedule 27.03.2010


Ответы (3)


Инициализация чего-либо самим собой — это неопределенное поведение, которое, возможно, может даже означать, что после его вызова вы даже не сможете обнаружить его позже. Предположим, компилятор это обнаружит и назло сгенерирует сборку для гнусавых демонов, а вовсе не вызов вашего конструктора копирования?

На практике можно предположить, что клиент не такой уж и тупой, а если и есть, то его дело отлаживать и разбираться.

person UncleBens    schedule 27.03.2010
comment
Где именно в стандарте сказано, что это поведение undefined? - person fredoverflow; 27.03.2010
comment
Честно говоря, я удивлен, что он вообще компилируется. Проблема в том, что конструктор копирования std::string попытается вызвать методы/данные доступа в x, но x еще не создан. Следовательно, это неопределенное поведение, потому что он будет пытаться делать что-то с переменной, которая еще не создана. - person Billy ONeal; 27.03.2010
comment
@FredOverflow: я думаю, что одна из важных частей стандарта - это точка объявления (3.3.1). Также возможно, что это имеет какое-то значимое применение, например, предположим, что класс хранит ссылку на другой экземпляр класса (или самого себя), тогда мы могли бы сделать, например: X x("self", x); X y("other", x); и т. д. В таком случае, я полагаю, правила будут аналогично использованию this в списке инициализации класса. - person UncleBens; 27.03.2010
comment
@FredOverflow, для ваших собственных классов я не думаю, что стандарт делает это неопределенным. Вы могли бы сделать struct X { X(X&){} }; X x(x); хотя такой класс не очень полезен, я думаю :) Для стандартных классов он делается неопределенным с помощью 17.4.3.7 аргументов функции. - person Johannes Schaub - litb; 27.03.2010

Вы не должны тестировать код, который пытается сломаться. См. раздел Нулевые ссылки. Это говорит

«Точно так же, как вы должны предполагать, что ненулевой указатель действителен, вы должны предполагать, что ссылка действительна. Вы должны верить в своих коллег-программистов».

я хочу дополнить

... вы должны предположить, что источник копии действителен.

Если вы "исправляете" свой случай, что делать для этого?

string x = string(x);
person Johannes Schaub - litb    schedule 27.03.2010

Тот код не корректен по стандарту и нет смысла его проверять и лучшее что может случиться это быстрый сбой, чтобы пользователь мог исправить свой код.

person David Rodríguez - dribeas    schedule 27.03.2010