Ссылка не может быть НУЛЕВОЙ, или это может быть ПУСТЫМ?

Я читал из Википедии что:

“Ссылки не могут быть нулевыми, тогда как указатели могут; каждая ссылка относится к некоторому объекту, хотя это может или не может быть допустимо”.

Но я не верю из-за следующего кода, смотрю на него, компилятор не дает ошибки:

class person
{
  public:
    virtual void setage()=0;
};

int main()
{
  person *object=NULL;
  person &object1=*object;
}

Разработайте эту точку.

9
задан leiyc 17 June 2019 в 09:04
поделиться

5 ответов

Сказать Person & Object1 = * Объект не то же самое, что говорит Person & Object1 = NULL . Вероятно, компилятор просто не достаточно умный, чтобы выяснить, что вы в любом случае, вы будете разыграть нулевой указатель, но вы получите ошибку выполнения. Так что они вещи истины до сих пор;)

10
ответ дан 4 December 2019 в 06:22
поделиться

Это произошло бы потерпеть вашу программу. Вы пытались запустить его? Делая * Объект будет удерживать нулевой указатель, поэтому на самом деле ваша ссылка никогда не назначается.

3
ответ дан 4 December 2019 в 06:22
поделиться

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

3
ответ дан 4 December 2019 в 06:22
поделиться

Одна оптимизация - вы преобразуете список файлов в набор при каждом вызове returnMatches, несмотря на то, что он никогда не меняется. переместите преобразование в начало функции «locate» и передайте набор в каждой итерации.

-121--2835542-

Есть ли способ сигнализировать о сбое построителя, и атрибут должен оставаться сброшенным?

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

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

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

sub get_fh {                                                                
  my $self = shift;                                                         

  my $abs_loc = $self->abs_loc;                                             

  if ( !(-e $abs_loc) || -e -z $abs_loc ) {                                 
    $self->error({ msg => "Critical doesn't exist or is totally empty" });  
    die "Will not run this, see above error\n";                             
  }                                                                         

  my $st = File::stat::stat($abs_loc);                                      
  $self->report_datetime( DateTime->from_epoch( epoch => $st->mtime ) );    

  my $fh = IO::File->new( $abs_loc, 'r' )                                   
    || die "Can not open $abs_loc : $!\n"                                   
  ;                                                                         

  $fh;                                                                      

}                                                                           

Совершенно другим подходом является подкласс IO:: File с метаданными файла, который требуется сохранить. Иногда это является эффективным и отличным решением:

package DM::IO::File::InsideOut;
use feature ':5.10';
use strict;
use warnings;

use base 'IO::File';

my %data;

sub previouslyCreated {
  $data{+shift}->{existed_when_opened}
}

sub originalLoc {
  $data{+shift}->{original_location}
}

sub new {
  my ( $class, @args ) = @_;

  my $exists = -e $args[0] ? 1 : 0;

  my $self = $class->SUPER::new( @args );

  $data{$self} = {
    existed_when_opened => $exists
    , original_location => $args[0]
  };

  $self;

};
-121--3119868-

В вашем коде:

person *object=NULL;
person &object1=*object;

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

И для решения другой части вашего вопроса, только потому, что программа компилируется, нет никакой гарантии, что она правильная или что она будет работать. Компиляторы C++ не обязаны даже пытаться диагностировать ошибки, содержащиеся в коде.

20
ответ дан 4 December 2019 в 06:22
поделиться

Ну, вы можете делать все, что хотите вы на C++. Другой пример:

person &object1 = *( reinterpret_cast<person*>(0) );

Вы вызываете неопределенное поведение в приведенном выше случае, кроме случая, о котором Вы упомянули!

2
ответ дан 4 December 2019 в 06:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: