Действительно ли практика возврата является ссылочным злом переменной C++?

Я нашел решение. Получить ширину контейнера фрагмента, как только станет доступным. Установите новую ширину для всех ключей. Недействительные клавиши для перерисовки клавиатуры. Для отступа слева в строках 2,3 и 4 я просто добавил количество клавиш с высотой = 0 перед первым ключом каждой строки.

//Here we wait for the fragment width to be available
currentView.post(new Runnable() {
        @Override
        public void run() {
            //Set the new width to the keys of the keyboard
            fixKeyboard(mKeyboard, currentView.getWidth());
            //Force redraw the keyboard
            mKeyboardView.invalidateAllKeys();
        }
    });
//...

private void fixKeyboard(Keyboard k, int dw)
{
    List<Keyboard.Key> keys = k.getKeys();

    int key_width = (dw / 11) - 2; //-2 for margin-right
    int row_number = 0;
    int pos_y = 0;
    int key_index_in_row = 0;
    for (Keyboard.Key key : keys)
    {
        if (key.y != pos_y)
        {
            pos_y = key.y;
            row_number++;
            key_index_in_row = 0;
        }

        //Space key
        if(row_number == 3 && key_index_in_row == 3)
        {
            key.width = 5 * key_width;
        }

        //Delete key
        else if(row_number == 0 && key_index_in_row == 10)
        {
            key.width = key_width + 4; //Slightly larger
        }
        else
        {
            key.width = key_width;
        }

        key.gap = 0;

        key.x = key_width * key_index_in_row;
        key_index_in_row++;
    }
}

С этим XML

<?xml version="1.0" encoding="utf-8"?>
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
android:keyWidth="8.5%p"
android:keyHeight="7%p"
android:keyEdgeFlags="left">

<Row>
    <Key android:keyLabel="Q" android:keyEdgeFlags="left" />
    <Key android:keyLabel="W" />
    <Key android:keyLabel="E" />
    <Key android:keyLabel="R" />
    <Key android:keyLabel="T" />
    <Key android:keyLabel="Z" />
    <Key android:keyLabel="U" />
    <Key android:keyLabel="I" />
    <Key android:keyLabel="O" />
    <Key android:keyLabel="P" />
    <Key android:codes="55000"  android:keyIcon="@drawable/del_keyboard" android:isRepeatable="true" android:keyWidth="15%p" android:keyEdgeFlags="right" />
</Row>
<Row>
    <Key android:keyLabel=" " android:keyHeight="0px" android:keyWidth="0px" android:keyEdgeFlags="left"/>
    <Key android:keyLabel="A" />
    <Key android:keyLabel="S" />
    <Key android:keyLabel="D" />
    <Key android:keyLabel="F" />
    <Key android:keyLabel="G" />
    <Key android:keyLabel="H" />
    <Key android:keyLabel="J" />
    <Key android:keyLabel="K" />
    <Key android:keyLabel="L" android:keyEdgeFlags="right" />
</Row>
<Row>
    <Key android:keyLabel=" " android:keyHeight="0px" android:keyEdgeFlags="left"  android:keyWidth="0px"/>
    <Key android:keyLabel=" " android:keyHeight="0px" android:keyWidth="0px"/>
    <Key android:keyLabel="Y" />
    <Key android:keyLabel="X" />
    <Key android:keyLabel="C" />
    <Key android:keyLabel="V" />
    <Key android:keyLabel="B" />
    <Key android:keyLabel="N" />
    <Key android:keyLabel="M" android:keyEdgeFlags="right" />
</Row>
<Row>
    <Key android:keyLabel=" " android:keyHeight="0px" android:keyWidth="0px" android:keyEdgeFlags="left"/>
    <Key android:keyLabel=" " android:keyHeight="0px" android:keyWidth="0px"/>
    <Key android:keyLabel=" " android:keyHeight="0px" android:keyWidth="0px"/>
    <Key android:codes="55001"  android:keyEdgeFlags="left"  android:keyIcon="@drawable/white_space_keyboard" android:keyWidth="50%p" />
</Row>

325
задан 8 revs, 5 users 88% 29 August 2018 в 22:13
поделиться

9 ответов

В общем, возвращение ссылки совершенно нормально и происходит постоянно.

Если вы имеете в виду: [1231 Это все виды зла. Выделенный в стеке i исчезнет, ​​а вы ни на что не ссылаетесь. Это также зло:

int& getInt() {
    int* i = new int;
    return *i;  // DON'T DO THIS.
}

Потому что теперь клиент должен в конечном итоге сделать странное:

int& myInt = getInt(); // note the &, we cannot lose this reference!
delete &myInt;         // must delete...totally weird and  evil

int oops = getInt(); 
delete &oops; // undefined behavior, we're wrongly deleting a copy, not the original

Обратите внимание, что ссылки на rvalue по-прежнему являются просто ссылками, поэтому все вредоносные приложения остаются неизменными.

Если вы хотите выделить что-то, что живет за пределами функции, используйте умный указатель (или вообще контейнер):

std::unique_ptr<int> getInt() {
    return std::make_unique<int>(0);
}

И теперь клиент хранит умный указатель:

std::unique_ptr<int> x = getInt();

Ссылки также хороши для доступа к вещам, где вы знаете, что время жизни остается открытым на более высоком уровне, например:

struct immutableint {
    immutableint(int i) : i_(i) {}

    const int& get() const { return i_; }
private:
    int i_;
};

Здесь мы это знаем

395
ответ дан 6 revs, 4 users 96% 23 November 2019 в 00:53
поделиться

I столкнулся с реальной проблемой, где это было действительно зло. По сути, разработчик вернул ссылку на объект в векторе. Это было плохо !!!

Полные подробности, о которых я писал в Janurary: http://developer-resource.blogspot.com/2009/01/pros-and-cons-of-returing-references.html

-2
ответ дан 2 revs, 2 users 77% 23 November 2019 в 00:53
поделиться

Функция как lvalue (иначе говоря, возвращение неконстантных ссылок) должна быть удалена из C ++. Это ужасно не интуитивно понятно. Скотт Мейерс хотел использовать min () с таким поведением.

min(a,b) = 0;  // What???

, которое на самом деле не является улучшением

setmin (a, b, 0);

. Последнее даже имеет больше смысла.

Я понимаю, что функция как lvalue важна для потоков в стиле C ++, но это Стоит отметить, что потоки в стиле C ++ ужасны. Я не единственный, кто так думает ... насколько я помню, у Александреску была большая статья о том, как сделать лучше,

-1
ответ дан Dan Olson 23 November 2019 в 00:53
поделиться

«возвращать ссылку - это зло, потому что, просто [как я понимаю] это делает проще пропустить его удаление "

Не верно. Возврат ссылки не подразумевает семантику владения. То есть, только потому, что вы делаете это:

Value& v = thing->getTheValue();

... не означает, что вы теперь владеете памятью, на которую ссылается v;

Однако, это ужасный код:

int& getTheValue()
{
   return *new int;
}

Если вы делаете что-то подобное, потому что «вам не нужен указатель на этот экземпляр» , тогда: 1) просто разыменуйте указатель, если вам нужен ссылка, и 2) вам в конечном итоге понадобится указатель, потому что вы должны сопоставить новое с удалением, и вам нужен указатель для вызова удаления.

10
ответ дан 2 revs 23 November 2019 в 00:53
поделиться

Это не зло. Как и многие вещи в C ++, это хорошо, если используется правильно, но есть много подводных камней, о которых вы должны знать при использовании (например, возвращая ссылку на локальную переменную).

Есть хорошие вещи, которые могут быть достигнуты с этим ( как карта [имя] = "привет мир")

14
ответ дан Mehrdad Afshari 23 November 2019 в 00:53
поделиться

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

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

Вы можете вернуть ссылку на что-то независимое от функции, которую вы не делаете. Не ожидайте, что вызывающая функция возьмет на себя ответственность за удаление. Это относится к типичной функции operator [] .

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

46
ответ дан 2 revs, 2 users 89% 23 November 2019 в 00:53
поделиться

Нет. Нет, нет, тысячу раз нет.

То, что зло, - это ссылка на динамически размещенный объект и потеря первоначального указателя. Когда вы создаете новый объект, вы берете на себя обязательство гарантированно удалить .

Но взгляните, например, на operator << : that должен вернуть ссылку, иначе

cout << "foo" << "bar" << "bletch" << endl ;

не будет работать.

64
ответ дан Charlie Martin 23 November 2019 в 00:53
поделиться

Not only is it not evil, it is sometimes essential. For example, it would be impossible to implement the [] operator of std::vector without using a reference return value.

4
ответ дан anon 23 November 2019 в 00:53
поделиться

There are two cases:

  • const reference --good idea, sometimes, especially for heavy objects or proxy classes, compiler optimization

  • non-const reference --bad idea, sometimes, breaks encapsulations

Both share same issue -- can potentially point to destroyed object...

I would recommend using smart pointers for many situations where you require to return a reference/pointer.

Also, note the following:

There is a formal rule - the C++ Standard (section 13.3.3.1.4 if you are interested) states that a temporary can only be bound to a const reference - if you try to use a non-const reference the compiler must flag this as an error.

7
ответ дан 23 November 2019 в 00:53
поделиться
Другие вопросы по тегам:

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