假设我有一个对象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之间发生了变化。
答案 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
这个班。
您的代码看起来正确地执行此操作。