LINUX.ORG.RU

В С++ невозможны анонимные ссылки?

 


0

1

Есть метод принимающий ссылку.

bool someMethod( MyObject& ref )
. Могу ли я передать ссылку на анонимный объект? Когда я пишу так:
someMethod( MyObject() )
, имею ошибку компиляции.

★★

Последнее исправление: mio (всего исправлений: 1)

Анонимная ссылка? Что за бред? Может ты так хотел:

bool someMethod( const MyObject& ref )

bool someMethod( MyObject() )

nanoolinux ★★★★
()
bool someMethod( MyObject() )

Во-первых, зачем здесь () после MyObject? Во-вторых, что ты потом будешь делать с этим объектом? Как к нему обращаться? Если это чисто хеадер, то что мешает написать

bool someMethod(MyObject&)

?

PS: C++ ненужен, изучай haskell.

anonymous
()

имею ошибку компиляции.

Добавь const.

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

Он, видимо, про вызов метода в коде — someMethod(MyObject), someMethod(MyObject{}), someMethod(MyObject()) при явном или нет дефолтном конструкторе, bool перед не нужен. Вполне делается с помощью const lvalue reference / mutable rvalue reference (C++11).

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

Сорри, имел ввиду вызов метода конечно же. Объект мне не нужен, вызов ради побочного эффекта

mio ★★
() автор топика

имею ошибку компиляции.

Какую?

no-such-file ★★★★★
()
Ответ на: комментарий от mio

Объект мне не нужен, вызов ради побочного эффекта

Ну тогда пусть будет const& вместо &. Таким образом можно принимать ссылок на временные («анонимные») объекты сколько угодно, вплоть до возможности строить сложные expressions — someMethod(someCopy(SomeCon1(SomeCon2(...), SomeCon3(...)))) (везде подразумевается const& у аргументов, чтобы без копирований).

quasimoto ★★★★
()
Последнее исправление: quasimoto (всего исправлений: 1)

сделай лучше себе 2 метода

bool someMethod(const MyObject& lvalue)
bool someMethod(MyObject&& rvalue)

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

Во-первых, зачем здесь () после MyObject

чтобы создать объект класса MyObject?

C++ ненужен, изучай haskell.

с такими успехами в C++, как у тебя, анон, держись лучше подальше от хаскелла. И вообще от программирования.

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

Привет, утечка памяти.

Познания местных в программировании вообще и в крестах в частности просто поражают.

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

Во, можешь мне обьяснить, что это за фишка такая. И как она работает?

Думаю понятно зачем оно нужно, но на всякий случай - иногда выгоднее просто «отдать» значение, чтобы не копировать. Скажем, передаём параметр в конструктор - внутри он сохраняется (копируется) всё равно. Это примерно как передача unique_ptr (передача владения).

Работает довольно просто. Например, есть у нас свой класс для строк:

class mega_string
{
  char *m_data;
  size_t m_size;
};

Копирование реализовано обычно:

mega_string::mega_string(mega_string const &other)
{
  m_size = other.m_size;
  m_data = new char[m_size];
  std::copy(other.m_data, other.m_data + m_size, m_data);
}

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

mega_string::mega_string(mega_string &&other)
{
  m_size = other.m_size;
  m_data = other.m_data;
  other.m_data = nullptr;
}
В итоге нет лишнего копирования и удаления.

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

Выше пример с классом string и && в конструкторе. Он же — http://stackoverflow.com/q/3106110 («It's only 10 pages on my monitor» :)). Вот ещё на почитать — https://www.artima.com/cppsource/rvalue.html, http://www.cprogramming.com/c 11/rvalue-references-and-move-semantics-in-c ..., http://stackoverflow.com/q/1116641, http://stackoverflow.com/q/5770253.

То есть принимать && это всё равно что принимать & (не const), только с той разницей, что в случае & мы можем передать только lvalue, то есть, допустим, некую переменную x связанную (слева, т.е. объявлением с конструктором) с куском стека вызывающей функции — принимающая принимает ссылку (фактически указатель) на кусок стека вызывающей функции, может этот кусок изменять, может вернуть ссылку на него обратно. Теперь, если мы передаём rvalue, например временный объект, например в случае someFunc(string1 + string2), то этот временный объект (от string1 + string2) тоже (допустим!) существует на стеке вызывающей функции, но не связан с какой-либо переменной (не l, а r, то есть просто выражение дающее временный объект), прилетит тот же указатель на кусок стека, но он виден только принимающей функции — если это конструктор копирования, то ему не нужно ничего копировать, объект уже есть, он уникально наш, можно его просто подобрать (поэтому move); в случае просто функции или метода — можно его подобрать и вернуть (обычную) ссылку на него вызывающей стороне — так мы можем этот временный объект превратить в обычное lvalue.

Это примерно про && в аргументах конструкторов, функций и методов. Ещё её можно возвращать — метод временного объекта может возвращать && на часть объекта, так что вызывающий будет подбирать (move) именно её.

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

#include <cstdio>
#include <string>
#include <memory>
 
struct A {
    std::string label;
    int x;
    void print() const {
        printf("A{%s}{%d}[%p]\n", label.c_str(), x, this);
    }
};

A const& f(A const& x) {
    printf("f-const on ");
    x.print();
    return x;
}

A& f(A&& x) {
    printf("f-mut on ");
    x.print();
    x.x += 1;
    return x;
}

A&& g(A&& x) {
    printf("g on ");
    x.print();
    x.x += 2;
    return std::move(x);
}

A h(A const& x) {
    printf("h on ");
    x.print();
    return A{"copy-tmp", x.x + 3};
}

int main() {
    int stack_starts;
    printf("main stack starts at %p\n", &stack_starts);
    // main stack starts at 0x7fff341008ec
    A lvalue{"lvalue1", 1};
    lvalue.print();
    // A{lvalue1}{1}[0x7fff341008d8]
    f(lvalue).print();
    // f-const on A{lvalue1}{1}[0x7fff341008d8]
    // A{lvalue1}{1}[0x7fff341008d8]
    f(std::move(lvalue)).print();
    // f-mut on A{lvalue1}{1}[0x7fff341008d8]
    // A{lvalue1}{2}[0x7fff341008d8]
    f(A{"tmp1", 2}).print();
    // f-mut on A{tmp1}{2}[0x7fff341008b0]
    // A{tmp1}{3}[0x7fff341008b0]
    g(std::move(lvalue)).print();
    // g on A{lvalue1}{2}[0x7fff341008d8]
    // A{lvalue1}{4}[0x7fff341008d8]
    g(A{"tmp2", 3}).print();
    // g on A{tmp2}{3}[0x7fff34100898]
    // A{tmp2}{5}[0x7fff34100898]
    h(lvalue).print();
    // h on A{lvalue1}{4}[0x7fff341008d8]
    // A{copy-tmp}{7}[0x7fff34100880]
    h(A{"tmp3", 4}).print();
    // h on A{tmp3}{4}[0x7fff2aa25c50]
    // A{copy-tmp}{7}[0x7fff2aa25c60]
    lvalue.print();
    // A{lvalue1}{4}[0x7fff341008d8]
}
quasimoto ★★★★
()
Последнее исправление: quasimoto (всего исправлений: 2)
Ответ на: комментарий от quasimoto

DarkEld3r
Спасибо всем за ценную информацию.
Я так понял, что это передача параметра по ссылке, но при этом мы говорим, что функция деструктивна для этого параметра.

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

это передача параметра по ссылке, но при этом мы говорим, что функция деструктивна для этого параметра

Да, только это же справедливо для обычного &. Как и && может быть const, как &, тогда нет деструктивности. Разница в том, что & работает с нормальными объектами (в т.ч. деструктивно) и НЕ работает со временными (кроме как по const&, но оно не используется при наличии версии с &&), а && работает со временными (тоже в т.ч. деструктивно) и НЕ работает с обычными (если только не сделать им std::move) — перегрузив функцию можно выбирать что делать с обычными (они сконструированы каким-то владельцем), а что со временными (нет владельца). Относительно объектов — может нам не нужна семантика копирования вообще, тогда сам объект может не реализовывать copy семантику, только move в своих конструкторах, тогда будет возможность агрегировать/принимать/возвращать не copyабельный, но movабельный объект.

quasimoto ★★★★
()

Могу ли я передать ссылку на анонимный объект?

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

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

Привет, утечка памяти.

не будет никакой утечки. Будет ошибка компиляции, т.к. метод ждёт ссылку, а ему пихают указатель.

Познания местных в программировании вообще и в крестах в частности просто поражают.

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

1. метод не умеет удалять объект?

2. operator new делает утечки и не использует GC?

emulek
()
21 декабря 2014 г.
Ответ на: комментарий от emulek

то откуда тебе знать

Откуда тебе знать, что в каком-то зачуханном объектнике operator new() не переопредён на if (rand() % 3000 == 0) return «kek»;

Или что этот указатель случайно неявно кастуется к смарт-поинтеру через пять преобразований.

Есть же некоторый здравый смысл и всё такое.

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

Есть же некоторый здравый смысл и всё такое.

ну если программист пишет foo(new bar), то очевидно, он как-то переопределил new. Иначе его проект просто не соберётся.

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