LINUX.ORG.RU

Вопрос по С++


0

0

Код:

class Class
{
  public:
    std::string get_str( void ) const
    {
      return str;
    }
  private:
    std::string str;
};

1. Стоит ли в функции get_str возвращать не std::string а std::string& или вообще const std::string&
Как я понимаю, в основной программе будет переменная ссылаться на class.str, и после удаления 
переменной class ссылка станет недействительной. Но с другой стороны это будет быстрее, и отпадёт второй вопрос.

2. Если я поставлю throw() в спецификации функции, будет ли это правильно? Т.е. если не будет хватать памяти и 
вызовется std::bad_alloc в конструкторе или операторе копирования строки, будет ли это исключение считаться 
исключением функции, ведь по сути тело функции выполняется без ошибок.
★★★★★

Ответ на: комментарий от phrm

> const std::str& get_str(void) const

И что ? Это не гарантирует что member класса не будет уничтожен,
вопрос про валидность ссылки был

mumg
()
Ответ на: комментарий от mumg

1) наверное все же проще взять и отслеживать синхронизацию удаления объектов, скорость и расход памяти будет экономится, но сложнее будет реализация.

mumg
()
Ответ на: комментарий от mumg

понятно, спасибо. А если я пишу
std::string str = cl.get_str();

то str это другая строка, не зависящая от cl правильно?

Legioner ★★★★★
() автор топика
Ответ на: комментарий от Legioner

да правильно, кроме того если возвращаешь ссылку, то надо явно
документировать время ее жизни( условия при который она инвалидируется )

aton
()

Про исключения:

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

aton
()
Ответ на: комментарий от aton

К плачевным результатам - имеется ввиду вызов функции unexpected() ? Понятно, спасибо.

А почему геморроя больше? Мне лично они понравились тем, что видно сразу, чего можно ожидать от функции, некоторая автодокументируемость.

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

Legioner ★★★★★
() автор топика
Ответ на: комментарий от Legioner

Скажу несколько вещей по поводу исключений:

1) Непортируемость, есть не только GCC :) а еще ADS например
2) Порождение большого количества исключений при большом дереве 
наследования только запутает
3) ....

mumg
()
Ответ на: комментарий от Legioner

> А почему геморроя больше? 

Например, если ты пишишь template function то однозначную спецификацию определить будет ( практически ) невозможно. Теже грабли и при 
полиморфизме.

> что видно сразу, чего можно ожидать от функции, некоторая 
> автодокументируемость.

Если метод кидает спец. исключения, то это должно быть описано,
как минимум, в его комментах.

> К тому же если я ожидаю, что функция может вызывать только такие 
> исключения, а запускается другое - значит что-то идёт не так.

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


aton
()
Ответ на: комментарий от Legioner

На мой взгяд оправданным является использование, только лишь, пустой
специализации ( throw() ), на каких то компиляторах это даже дает
прирост в производительности. При такой стратегии, получается что если:

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

aton
()
Ответ на: комментарий от mumg

>> const std::str& get_str(void) const

> И что ? Это не гарантирует что member класса не будет уничтожен, > вопрос про валидность ссылки был

Вопрос глуп. Попробуй написать этот код (с проявлением невалидности ссылки). Его невозможность и будет тебе ответом.

gpg
()
Ответ на: комментарий от gpg

> Вопрос глуп. Попробуй написать этот код (с проявлением невалидности ссылки). Его невозможность и будет тебе ответом.

Еще как возможен, вот хотя бы этот пример:

#include <iostream>
#include <string>

class foo
{
public:
	foo()
		:	s_( "zhopa" )
	{}
	const std::string& get_s() const { return s_; } 
private:
	std::string s_;
};

const std::string&  bar()
{	
	foo f;
	return f.get_s();
}

int main()
{
	std::cout << bar() << std::endl;
}

---

bar вернет провисшую ссылку.

aton
()
Ответ на: комментарий от aton

А теперь замени метод (foo::get_s), возвращающий ссылку, на метод, возвращающий строку по значению, и скажи, что изменилось.

gpg
()
Ответ на: комментарий от aton

Сразу поясню во избежание.
То, что ты написал, а именно тело bar() иллюстрирует случай возвращения ссылки на локальную переменную.
Так писать нельзя. Вне зависимости от того, откуда взялась эта локальная переменная.
Вопрос, собственно, в том, а причём тут foo::get_s?

const std::string& bar()
{
return std::string();
}

Это что-то изменило?

Ещё раз повторю. За bar надо увольнять. foo::get_s абсолютно безопасна.

gpg
()
Ответ на: комментарий от gpg

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


aton
()

boost::shared_ptr спасет отца русской демократии.

С другой стороны, насколько я помню, в нормальных системах std::string - copy-on-write-ная, т.е. ее можно смело возвращять по значению, и если она не редактируется - то это будет достаточно эффективно.

anonymous
()
Ответ на: комментарий от gpg

> то, что ты написал, а именно тело bar() иллюстрирует случай 
> возвращения ссылки на локальную переменную.

Вот тебе еще примеры инвалидирования ссылки, доказывающие существования
такого эффекта как такового:


#include <iostream>
#include <string>

class foo
{
public:
	foo()
		:	s_(" lalla" )
	{}
	const std::string& get_s() const { return s_; }
private:
	std::string s_;
};

int main()
{
	const std::string& s1 = foo().get_s();

	foo *f_ptr = new foo;
	const std::string& s2 = f_ptr->get_s(); 
	delete f_ptr;
}

> Ещё раз повторю. За bar надо увольнять. foo::get_s абсолютно 
> безопасна.

Еще раз... Это был пример для тебя и только. Но ситуации с инвалидированием ссылки возможны!




aton
()
Ответ на: комментарий от anonymous

> в нормальных системах std::string - copy-on-write-ная

Это только в __ненормальных__ системах!

> если она не редактируется - то это будет достаточно эффективно

если она не редактируется делают так:

std::string foo()
{
  std::string s( "llsslls" );
  ...
  return s; // стандартом разрешено не создовать временных переменных,
и они как правило их и не создают. 
}

int main()
{
  const std::string& s = foo(); // Константная ссылка продливает время жизни объекта.
}

aton
()
Ответ на: комментарий от aton

Ещё раз.
Твой пример совсем про другое. В нём инвалидируется ссылка на _локальную_ переменную. Первоначальный вопрос был про возвращение ссылки на _мембер_. А ссылка на мембер валидна во всей области её видимости.
Перечитай всё ещё раз, что ли.

gpg
()
Ответ на: комментарий от aton

8<------------------------------------- std::string foo() { std::string s( "llsslls" ); ... return s; // стандартом разрешено не создовать временных переменных, и они как правило их и не создают. }

int main() { const std::string& s = foo(); // Константная ссылка продливает время жизни объекта. } 8<------------------------------------- "Константная ссылка продливает время жизни объекта." По поводу этого. Где можно прочитать про такое чудо? Меня учили, что временный объект уничтожается по выходу из строки, в которой был создан.

gpg
()
Ответ на: комментарий от gpg

Фантастика, майкрософтовский компилятор держит объект даже при неконстантной ссылке!
Тем не менее, нельзя ли услышать номерочек пунктика стандарта?

gpg
()
Ответ на: комментарий от aton

Либо я попросту забью.
Даже если это и есть в стандарте, я всё равно этим пользоваться не буду,
ибо кроме путанницы, никаких плюсов я не вижу.

gpg
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.