Компилятор C ++, принудительная передача по ссылке - PullRequest
0 голосов
/ 23 сентября 2019

Можно ли по умолчанию установить компилятор C ++ для интерпретации всей передачи параметров как ссылки, определяющей новый модификатор, указывающий, что вам нужен проход за копию.

Программирование Я обнаружил, что только по-настоящемунужно передавать данные по копии, чтобы, по крайней мере для меня, было бы гораздо эффективнее иметь «ссылку по умолчанию»

Ответы [ 2 ]

3 голосов
/ 23 сентября 2019

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

Рассмотрим эту простую правильно сформированную программу:

struct X {};

auto bar(X x) -> decltype(x)
{
    return x;
}

auto test()
{
    bar(X{});
}

Как бы вы ее преобразовали?Невозможно заставить bar взять ссылку и не изменять семантику программы или сделать ее UB

Если вы сделаете bar ссылку на l-значение, тогда она не сможет принять временную:

struct X {};

auto bar(X& x) -> decltype(x)
{
    return x;
}

auto test()
{
    bar(X{});
}
<source>:12:5: error: no matching function for call to 'bar'

    bar(X{});

    ^~~

<source>:4:6: note: candidate function not viable: expects an l-value for 1st argument

auto bar(X& x) -> decltype(x)

     ^

1 error generated.

Если вы возьмете ссылку на r-значение, вы не сможете вернуть ее без дальнейших изменений:

struct X {};

auto bar(X&& x) -> decltype(x)
{
    return x;
}

auto test()
{
    bar(X{});
}
<source>:6:12: error: rvalue reference to type 'X' cannot bind to lvalue of type 'X'

    return x;

           ^

1 error generated.

Хорошо, вы можете решить эту конкретную проблему, переместив параметр.Но это намного выше того, что вы изначально хотели изменить.Тем не менее, ради аргумента, скажем, вы делаете, или что оригинальная программа уже делала это:

#include <utility>

struct X { };

auto bar(X&& x) -> decltype(x)
{
    return std::move(x);
}

auto test()
{
    bar(X{});
}

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

// before

#include <utility>

struct X { auto foo() const {} };

auto bar(X x) -> decltype(x) // bar returns a prvalue
{
    return x;
    // or
    // return std::move(x); // redundant, but valid and equivalent
}

auto test()
{
    const X& xr = bar(X{}); // xr prolongs the lifetime of the temporary returned by `bar`

    xr.foo(); // OK, no problem
}
// after

#include <utility>

struct X { auto foo() const {} };

auto bar(X&& x) -> decltype(x) // now bar returns an xvalue
{
    return std::move(x);
}

auto test()
{
    const X& xr = bar(X{}); // xr cannot prolong the life of an xvalue
    // the temporary objects created as part of calling `bar` is now expired
    // and xr references it
    // any attempt to use xr results in UB

    xr.foo(); // Undefined Behaviour
}

Невозможно сделать то, что вы хотите сделать.

Бремя лежит на васПрограммист: если вам нужны значения, пишите значения, если вам нужны ссылки, пишите ссылки.Это так просто.

2 голосов
/ 23 сентября 2019

Нет.

Я не слышал ни о каком компиляторе, имеющем эту функцию.

...