朋友说明符的范围限制是什么

时间:2014-12-17 09:17:38

标签: c++ c++11 design-patterns proxy friend

假设我有一个对象X和一个代理。我想控制代理的生命周期,以便它不能扩展到临时对象之外,由X的方法返回。我无法理解我这样做是因为标准允许的。

class X
{
public:
    struct Proxy
    {
        ~Proxy();

        /// Implicit convertion to wrapped object.
        operator X &();
        operator const X &() const;

        /// Explicit access to wrapped object.
        X & get();
        const X & get() const;

    private:
        friend class X;

        Proxy(X & x_ref);
        Proxy(Proxy && other) noexcept;

        Proxy(const Proxy &) = delete;
        Proxy & operator = (const Proxy&) = delete;
        Proxy & operator = (Proxy && other) = delete;

        X & _x_ref;
    };

    Proxy get_proxy() {
        Proxy proxy(*this);
        // ...
        return proxy;
    }
};

具体来说,我担心从X::get_proxy()方法返回对象时的部分。从技术上讲,谁调用移动构造函数,将一个对象从方法体移动到临时对象中,这是该方法的返回值?标准是否说它是在X的范围内完成的,所以friend说明符在这里正常工作?

它在没有GCC 4.7-4.9和clang 3.0-3.5的警告和错误的情况下进行编译。但我只需要第三方确认将来不会改变,因为这是一种标准化行为。

注意:这个代码示例可能看起来很愚蠢,但它是一个剥离的一般案例。在现实世界中,应用程序代理用于公开X的一些内部数据,而不是对X的引用。

注意:这里我使用移动构造函数,因为它是未来,是时候继续前进而忘记旧标准。但是这个代理可以用拷贝构造函数来代替。虽然这不会改变这个问题。除非此范围内的内容在c ++ 03和c ++ 11/14之间发生了变化。

1 个答案:

答案 0 :(得分:0)

考虑这个通用函数定义:

struct T { /* ... */ };   // to be sure that "T" is an object type

T foo()
{
    T x(1, 2, 3);
    return x;
}

函数foo返回T类型的prvalue。现在,函数评估foo()正式包含两个构造函数:首先构造x,然后构造返回值,即x复制或移动构造(取决于类型T)的详细信息。

最后,当你将其他地方的变量初始化为T a = foo();时,会有第三个正式的构造函数调用,即来自临时的a的复制构造。 (复制省略允许省略两个复制构造函数,效果可能就像您说过T a(1, 2, 3);

上述情况下的所有构造函数必须在它们被正式调用时才能访问。在我的缩短示例和原始代码中,所有调用都不在T的成员函数内,因此如果构造函数为private,则调用站点需要为friend这个班。

您的代码看起来正确地执行此操作。