C ++: передача указателя на класс при его создании - PullRequest
1 голос
/ 05 декабря 2011

Если у меня есть class Foo и метод с прототипом void bar(Foo* foo). Это нормально делать: bar(&Foo());?

Я знаю, что он компилируется и работает, но, поскольку я относительно новичок в C ++, мне было интересно, будет ли созданный экземпляр правильно уничтожен после использования, или мне придется беспокоиться о чем-то еще при этом.

Ответы [ 5 ]

5 голосов
/ 05 декабря 2011

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

Это ограничение приведено в разделе §5.3.1 стандарта C ++:

Результатом унарного оператора & является указатель на его операнд. Операндом должно быть lvalue или квалифицированный идентификатор .

Временные значения являются prvalues, поэтому они не могут получить свой адрес.

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

2 голосов
/ 05 декабря 2011

Это не действительно, в общем случае.Foo() - это временный объект, который будет мертв, как только вернется bar.MSVC неправильно примет его как расширение.

1 голос
/ 05 декабря 2011

Если вы используете собственный C ++, вы можете отключить языковые расширения в MSVC2010.

Проект-> Свойства-> C / C ++ -> Язык-> Отключить языковые расширения.

struct Foo
{
};

void bar(Foo* foo)
{
}


int main()
{
    bar(&Foo());
}

Вывод:

1> ------ Сборка запущена: Проект: Тест, Конфигурация: Выпуск Win32 ------ 1> Test.cpp 1> Тест.cpp (16): ошибка C2102: '&' требуется l-значение ========== Построение: 0 выполнено, 1 не выполнено, 0 обновлено, 0 пропущено ==========

1 голос
/ 05 декабря 2011

Вы уверены, что код скомпилируется? С gcc вы получите error: taking address of temporary.

Причина, по которой вы не должны (а с некоторыми компиляторами не может ) взять адрес временного в том, что он выйдет из области видимости (поэтому будет уничтожен). / deconstructed), и адрес, переданный bar, не будет адресом реального Foo объекта, к которому у вас есть права доступа.

0 голосов
/ 05 декабря 2011

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

Более логичным подходом было бы переопределение функции безпараметры.

void bar(){ Foo f;  bar(&f);} 
void bar(Foo * ifoo){...}

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...