2013-02-13 7 views
3

Стандартная библиотека обычно допускает неопределенное поведение, если вы нарушаете любые требования к типам шаблонов, даете ошибочные аргументы функции или любое другое нарушение контракта. Является ли это хорошей практикой, позволяющей это делать в пользовательских библиотеках? Когда это справедливо?Когда справедливо целенаправленно вызывать неопределенное поведение?

Рассмотрит написание operator[] для контейнера:

template <typename t> 
T& container<T>::operator[](int i) 
{ 
    return internal_array[i]; 
} 

Если i индексов вне пределов internal_array, мы попали неопределенное поведение. Должны ли мы позволить этому произойти или выполнить проверку границ и выбросить исключение?

Другим примером является функция, которая принимает int аргумент, но только позволяет ограниченный домен:

int foo(int x) 
{ 
    if (x > 0 && x <= 10) { 
    return x; 
    } 
} 

Если x не находится в пределах области, исполнение достигнет конца функции без return заявления - это дает неопределенное поведение.

Должен ли разработчик библиотеки чувствовать себя плохо для разрешения этого или нет?

+1

Может быть, лучше подходит для программистов, я не знаю. – chris

+0

Лично: Если легко отладить диагностику в сборке отладки (например, с помощью утверждений или чего-то еще), я всегда нахожу это. Реализации стандартной библиотеки по крайней мере иногда следуют аналогичным рекомендациям: '[]' часто проверяет границы в отладочных сборках. ** Но ** никогда не было причин вызывать неопределенное поведение, если вы можете избежать его без дополнительных затрат времени исполнения - если вы уже проводите проверку границ, дайте хорошую диагностику. – Voo

+0

@chris Возможно. Я не был уверен. –

ответ

3

Когда справедливо целенаправленно вызывать неопределенное поведение?

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

Стандартная библиотека C++ 11 определяет множество таких функций: просто подумайте о индексе оператора для коллекций последовательностей.

Если вы спрашиваете это с точки зрения прикладного программиста, с другой стороны, ответ, конечно, «никогда», если не вы пишете, не переносимый код, который опирается на некоторые документально расширения вашего компилятора и/или некоторых функций вашей операционной системы (но тогда можно утверждать, что вы все еще говорите на C++).

Должен ли разработчик библиотеки чувствовать себя плохо для разрешения этого или нет?

Если это был случай, г-н. Степанов должен чувствовать себя ужасным. Нет, это не плохо, это зависит только от того, предназначена ли ваша библиотека для максимальной эффективности или максимальной безопасности - с множеством нюансов в середине.

1

Все это сводится к документации.

Наглядно вы не ожидали бы [] сделать любую проверку границ, но вы могли бы также обеспечить at метод к контейнеру, который бросает исключение (яй, так же, как люди, которые пишут std). Конечно, вы можете исключить исключение, но документировать это поведение.

Во-вторых, честная игра, и пока вы четко подтверждаете, что поведение не определено, если функция вызывается с плохими аргументами и, у вас есть все основания для этого (красный). Если вы разрабатываете критическую для производительности библиотеку, вам не нужны накладные расходы на проверку ввода. Если нет, выбросьте исключение.

+0

Лично я бы рассмотрел библиотеку, которая не выполняет простые проверки границ в сборке отладки (чтобы остаться с примером), плохо спроектирована. Например. каждая реализация 'std', которую я знаю, имеет утверждение, выполняющее проверку границ в' [] 'для векторов. Я даже не хочу оценивать, сколько ошибок было найдено по ошибке. – Voo