LINUX.ORG.RU

Нужен совет (С++: char * и string&)


0

0

Ситуевина такая:

В метод класса передаются параметры типа const char * (на этом этапе string& не использую, так как в этом методе отрабатывает функция сторонней С-библиотеки). Соответственно, имею private переменные-члены класса типа const char * (их столько же, сколько и параметров у метода). А поскольку это С++, то хочется забыть о char * и использовать string. В классе сучествуют методы доступа к этим const char * переменным.

Задача: сделать так, чтобы они возвращали результат типа string &.

Вопрос: как лучше всего сделать?

И пойдет ли так:

string& getA()

{

string _s(const_char_var);

return _s;

}

Вот только в этом случае возвращается ссылка на локальную _s.

Спасибо за ваши соображения по этому поводу.

anonymous

>И пойдет ли так: [...]

Нет. Ссылку на локальный объект возвращать нельзя.

Сделай так:
string getA()
{
string _s(const_char_var);
return _s;
}

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

Т.е в таком случае:

string my = a.getA();

в результате NRVO (Name Return Value Optimization) объект сконструируется сразу там, где надо, т.е это будет эквивалентно:

string my(a.const_char_var);



WFrag ★★★★
()

чтобы возвращалась ссылка не на локальную переменную, нужно использовать оператор new.

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

>чтобы возвращалась ссылка не на локальную переменную, нужно использовать оператор new.

Ты, блин, полегче с такими советами :) Какой new, куда new? Так что-ли:

sting& getA()
{
return *new string(const_char_variable);
}

За такое убивать надо! :)

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

>А как ты по другому возвратишь ссылку на объект?

Во-первых, можно вернуть ссылку на переменную объекта. Но это плохо. Очень плохо, поскольку ссылка может сохраниться, а объект - уже помереть.

А во-вторых, а зачем обязательно возвращать ссылку? Может найдется другое решение?

Сначала надо понять, чего хочет автор вопроса :)

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

> За такое убивать надо! :)

но не сразу: если такое буит происходить каждые 2 сек работы программы, то да. а если 1 раз - why not! + ко всему: кто тебе мешает высвободить этот стринг после использования?

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

>но не сразу: если такое буит происходить каждые 2 сек работы программы, то да. а если 1 раз - why not! + ко всему: кто тебе мешает высвободить этот стринг после использования?

Ну тут один раз прохалявишь, в другой раз что-нибудь еще криво напишешь. И поехало-понеслось :)

Высвободить-то можно, вот только владение объектом здесь очень не четкое. Возможны потенциальные проблемы, например, с исключениями.

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

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

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

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

Обосновать?

Ну, кто-то из великих как-то говорил про string, что в случае, когда надо получить значение этого типа, то лучше это делать по ссылке. А мне то надо будет вызывать этот метод неограниченное количество раз, а возвращаемое значение не изменяется в пределах копии объекта, и следить за уничтожением объекта типа string должен будет тот, кто будет использовать мой класс, так что это нежелательно. Вот. Заодно хочу спросить:

есть 3 варианта:

1. string getA(){

return string("A"); // или return "A"? Как лучше? :)

}

2. string& getA(){

return *new string("A");

}

3. string *getA() {

string &_s = *new string("A");

return &_s;

}

Понимаю, что возвращается во всех случаях, но что выбрать в каком случае? В чем их отличие в контексте применения? И что посоветуете конкретно в моем случае?

Очень благодарен!

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

>Ну, кто-то из великих как-то говорил про string, что в случае, когда надо получить значение этого типа, то лучше это делать по ссылке. А мне то надо будет вызывать этот метод неограниченное количество раз

Зависит от контекста. Если у тебя было бы поле типа std::string, то можно было бы просто возвращать константную ссылку на него (хотя это и не очень хорошо - ссылку клиент может сохранить, а объект убить).

>а возвращаемое значение не изменяется в пределах копии объекта, и следить за уничтожением объекта типа string должен будет тот, кто будет использовать мой класс, так что это нежелательно.

Почему? Если ты просто вернешь строчку по значению, то клиенту твоего класса не придется прилагать никаких усилий по слежению за временем жизни объекта.

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

2. Неинтуитивно. Как-то не принято так делать, по крайней мере не встречал такого. В любом случае, клиенту придется самостоятельно освобождать память, что плохо.

3. Можно, но сырые указатели - это зло. :) Потому что опять же придется вручную управлять временем жизни объекта, что чревато ошибками.

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

4.
А так?

[josephson@server temp]$ cat sample0.cpp
#include<string>
#include<fstream>

class Test{
        public:
        string getA(){
                static string _s="Test\n";
                return _s;}};

int main(void){
        Test Str;
        cout<<Str.getA();
        return 0;}
[josephson@server temp]$ g++ -o sample sample0.cpp
[josephson@server temp]$ ./sample
Test
[josephson@server temp]$

Или так?

[josephson@server temp]$ cat sample1.cpp
#include<string>
#include<fstream>

class Test{
        static string _s;
        public:
        string getA(){
                return _s;}};

string Test::_s="Test\n";

int main(void){
        Test Str;
        cout<<Str.getA();
        return 0;}
[josephson@server temp]$ g++ -o sample sample1.cpp
[josephson@server temp]$ ./sample
Test
[josephson@server temp]$

josephson ★★
()

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

Исключения - функции типа malloc

Здесь явное не тот случай.

Однако, string f(x) это тоже не очень хорошо.

Выход:

1. Глобальный объект класса string

2. функция получает указатель или ссылку на живой объект и меняет его

Второй вариант самый предпочтительный. Например:

int initialize_string(string& o_sport_ti_mir)

{ o_sport_ti_mir = "Poshli vse v sad!"; return NO_ERROR; }

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