Rvalue vector

daslex

Как это?
vector<int&&> v = {0,0,0};// Это не скомпилируется (Вектор, якобы, хранит rvalue)
vector<int> &&rval_vec = v; //Это не скомпилируется (Вектор, якобы, rvalue)
Встретил такое определение, как rvalue контейнер, и не понял, что это такое.
14 ответов

daslex

daslex, я могу дико ошибаться, но по определению STL контейнеры хранят копию и следовательно, она копирует ваши нули и они вовсе не rvalue.а 2 строка будет валидной, если первая скомпилируется и второя будет содержать std::moveP.S. Сложные у вас вечно вопрос) Где вопросики про что такое переменная - на такие я бы мог ответить, а тут снова ждать сторожил.


daslex

Я задам вопрос немного по-другому. Как вот в эту функцию
template <typename T, typename T2>
decltype(auto) foo(T& container, T2 index)
{
 
    return container[index]; 
}
Подать временный контейнер таким образом, чтобы он в неё не передался? В смысле, что он не должен туда передаваться. rvalue невозможно связать с lvalue (если только они не являются lvalue на константные объекты).Мне нужен такой rvalue, который не lvalue.Вот так можно.
foo(vector<int>{1,1,1,1,1,1,1,1,1,1}, 4) ; //rvalue отдаётся
Но мне ещё надо увидеть эффект висячей ссылки, что у этого временного вектора элемент прекращает своё существование после вызова функции.Как связаться с такой ссылкой на элемент такого контейнера, не понимаю.


daslex

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


daslex

В смысле, чтобы при передаче временного контейнера была ошибка компиляции?
template <typename T, typename T2>
decltype(auto) foo(T& container, T2 index)
{
 
    return container[index]; 
}
 
int main(){
   foo(vector<int>{1,1,1,1,1,1,1,1,1,1}, 4) = 25 ; //rvalue отдаётся, не компилируюсь. так и надо, 
                                                               //меняю на rvalue параметры функции,
                                                               //компилируется. ОК
   /*
Здесь нужно обратиться к элементу временного вектора и словить
   эффект висячей ссылки
*/
}


daslex

template <typename T, typename T2>
decltype(auto) foo(T&& container, T2 index)
{
    static_assert(std::is_lvalue_reference<T>::value, "T must be not rvalue");
    return container[index];
}


daslex

daslex, Че то нифига не понял. Вот висячая ссылка:
class MyContainer
{
    int data;
public:
    MyContainer() : data(0)
    {
        std::cout << "MyContainer() " << &data << std::endl;
    }
    MyContainer(MyContainer& r) : data(r.data)
    {
        std::cout << "MyContainer(MyContainer&)" << std::endl;
    }
    MyContainer(MyContainer&& r) : data(r.data)
    {
        std::cout << "MyContainer(MyContainer&&)" << std::endl;
    }
    ~MyContainer()
    {
        std::cout << "~MyContainer()" << std::endl;
    }
 
    int& getData() { return data; }
};
 
template<class T>
decltype(auto) foo(T& cont)
{
    std::cout << "In foo() " << &cont.getData() << std::endl;
    return cont.getData();
}
 
int main()
{
    int& ref = foo(MyContainer());
    std::cout << "Will modify " << &ref << std::endl;
    ref = 42;
}
Чуть изменил, чтоб совсем похоже было:
class MyContainer : public std::vector<int>
{
public:
    MyContainer() : std::vector<int>(1, 1)
    {
        std::cout << "MyContainer() " << &(*this)[0] << std::endl;
    }
    MyContainer(const MyContainer& r) : std::vector<int>(r)
    {
        std::cout << "MyContainer(MyContainer&)" << std::endl;
    }
    MyContainer(MyContainer&& r) : std::vector<int>(r)
    {
        std::cout << "MyContainer(MyContainer&&)" << std::endl;
    }
    ~MyContainer()
    {
        std::cout << "~MyContainer()" << std::endl;
    }
};
 
template<class T>
decltype(auto) foo(T& cont)
{
    std::cout << "In foo() " << &cont[0] << " " << cont[0] << std::endl;
    return cont[0];
}
 
int main()
{
    int& ref = foo(MyContainer());
    std::cout << "Will modify " << &ref << " " << ref << std::endl;
    ref = 42;
    std::cout << "Now " << &ref << " " << ref << std::endl;
}
Вывод:
MyContainer() 00A72988 In foo() 00A72988 1 ~MyContainer() Will modify 00A72988 -572662307 Now 00A72988 42


daslex

Эффективный и современный С++. 1.3 Знакомство с decltype.Только название функции у меня foo. Я не могу понять как поймать висячую ссылку. Что такое висячие ссылки я знаю. Я хочу её словить в конкретном примере.


daslex

daslex, Так у меня ж в выводе Все адреса совпадают, т.е. - это один объект. В третьей строке - вывод из деструктора, т.е. объект уничтожен. В четвертой строке видно мусор (UB, в данном случае проявилось так) В пятой строке видно измененоое значение висячей ссылки (42). Теперь надо ловить перезапись этой памяти. Это легче сделать из первого моего примера (там висячая ссылка указывает на стек, т.е. просто вызвать несколько новых функций и убедиться что данные затрутся)


daslex

Пример тяжело читается...


daslex

Пример тяжело читается...
Как смог


daslex

Время немного нужно. Просто отклонилось от простого минималистичного немного.Ваш пример и не компилируется в clang.А мне нужно понять, о чём толкует автор книги.я вижу xvalue, но не вижу висячести. ( в своём варианте кода)


daslex

daslex, я могу дико ошибаться, но по определению STL контейнеры хранят копию и следовательно, она копирует ваши нули и они вовсе не rvalue. а 2 строка будет валидной, если первая скомпилируется и второя будет содержать std::move P.S. Сложные у вас вечно вопрос) Где вопросики про что такое переменная - на такие я бы мог ответить, а тут снова ждать сторожил.
Действительно ошибаетесь. Первая строка не компилируется не потому, что нули не rvalue (они то как раз rvalue, а точней prvalue, которые являются rvalue), а потому что в терминологии стандарта ссылка - не объект, а посему нельзя хранить массив ссылок например, нельзя создать указатель на ссылку (но ссылку на указатель можно). Но если бы можно было создать такой вектор, как в первой строке, то вторая все равно-бы не скомпилировалась, ибо тип объекта на который ссылается ссылка и тип ссылки - разные
Я не могу понять как поймать висячую ссылку. Что такое висячие ссылки я знаю. Я хочу её словить в конкретном примере.
Тоже самое что и висячий указатель, только ссылка:
int& get_dangling_ref()
{
    int a = 10;
    return a;
}


daslex

Ваш пример и не компилируется в clang.
Замените decltype(auto) foo(T& cont) на decltype(auto) foo(T&& cont) http://rextester.com/live/ULEC6490


daslex

Я не могу понять как поймать висячую ссылку
template <typename T, typename T2>
decltype(auto) foo(T&& container, T2 index)
{
    return container[index];
}
 
int main()
{
    std::vector<int> v{1,2,3,4};
    foo(v, 0) = 42;
    std::cout << v.front();
    auto& good_ref = foo(v, 1);
    good_ref = 84;
    std::cout << v[1];
 
    auto& bad_ref = foo(std::vector<int>{1,2,3,4}, 0);
    bad_ref = 42;
}