简体   繁体   English

C ++中的智能引用

[英]Smart references in C++

Edit: Welp, I guess this was a terrible idea. 编辑:Welp,我想这是一个可怕的想法。

Is it possible to make a smart reference in C++ (for a specific class, since you can't overload the . operator) with the same semantics as a normal C++ reference, but which is reseated when used in an STL container? 是否可以使用与普通C ++引用相同的语义在C ++中创建一个智能引用(对于特定类,因为您不能重载。运算符),但是在STL容器中使用时会重新设置?

For example, if I have some int_ref class with the normal integer operators overloaded, and construction and assignment looks like this: 例如,如果我有一些int_ref类,正常的整数运算符重载,构造和赋值如下所示:

class int_ref{
    int * p;
public:
    int_ref(int * ip) : p(ip) {}
    int_ref(const int_ref & other) : p(other.p) { 
        /* maybe some refcounting stuff here */ 
    }
    int_ref & operator = (const int_ref & other){
        if (!p) 
            throw something_bad();
        *p = *other.p;
        return *this;
    }
    void reseat(const int_ref & other){
        p = other.p;
    }
}

Then I can't use this with std::vector since it won't reseat the references, and I don't want this kind of thing: 然后我不能将它与std::vector一起使用,因为它不会重置引用,我不想要这样的事情:

std::vector<int_ref> vec;
int_ref five = new int(5);
vec.push_back(five);
vec.push_back(new int(1));
std::sort(vec.begin(), vec.end()); // the value of five is now 1

I can use rvalue references to make it play nice with the STL, 我可以使用右值引用使它与STL一起玩得很好,

int_ref & operator=(int_ref && other){
    reseat(other);
    return *this;
}

But then a function that returns an int_ref would use the rvalue overload, and I'd get this: 但是返回一个int_ref的函数会使用rvalue重载,我会得到这个:

int_ref make_number(){
    return new int(10);
}

int_ref ref = new int(5);
int_ref other = ref;
other = make_number();    // instead of copying, as a reference would,
                          // other now points to something other than ref

Is there a way around this? 有没有解决的办法? Is this just a terrible idea in general? 这一般只是一个可怕的想法吗?

One problem with even trying to do this is operator& . 甚至尝试这样做的一个问题是operator& For a reference, it gives you the address of the referand (since references have no address). 作为参考,它为您提供了参考地址(因为参考没有地址)。 For a element of a container, though, it's expected to give you the address of the element (since those do have addresses). 但是,对于容器的元素,它应该为您提供元素的地址(因为它们具有地址)。

So, an element of a container cannot mimic reference semantics in this respect. 因此,容器的元素在这方面不能模仿引用语义。 If you overload operator& to return the address of the referand, then for example the contiguous storage guarantee of vector is violated, since it says &v[n] == &v[0] + n for all 0 <= n < v.size() 如果重载operator&返回referand的地址,那么例如违反了vector的连续存储保证,因为它表示&v[n] == &v[0] + n对于所有0 <= n < v.size()

boost::addressof() was invented to work around this problem, so that you don't have to use & to get the address of an object in generic code. boost::addressof()是为解决这个问题而发明的,因此您不必使用&来获取通用代码中对象的地址。 But even the standard is too lazy to say static_cast<T*>(&static_cast<char&>(v[n])) rather than &v[n] . 但即使标准也懒得说static_cast<T*>(&static_cast<char&>(v[n]))而不是&v[n] Even when you're thinking of using it, it's quite difficult to decide when you want the actual address of the object, and when you want the address that the author of the object thinks you want. 即使您正在考虑使用它,也很难确定何时需要对象的实际地址,以及何时需要对象作者认为您想要的地址。 It's best just never to overload unary operator& . 最好永远不要超过一元运算operator& That means you'll get a partial version of reference semantics, which potentially is confusing in its own way. 这意味着你将获得一个部分版本的引用语义,这可能会以自己的方式混淆。

What you probably want to use is a boost:ptr_{container}. 你可能想要使用的是一个提升:ptr_ {container}。

You store pointers in the container (and the container takes ownership). 您将指针存储在容器中(并且容器具有所有权)。 But when accessing the object you get references to the object not the pointer. 但是当访问对象时,您将获得对象的引用而不是指针。

#include <boost/ptr_container/ptr_vector.hpp>

int main()
{
     boost::ptr_vector<int>    data;
     data.push_back(new int(5));


     std::cout << data[0] << "\n";  // Prints 5 as you get a reference to the object.
}

Alternatively if you just want references. 或者,如果您只想要参考。 Then you can use boost:ref 然后你可以使用boost:ref

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM