C++ 友元说明符的范围限制是什么
假设我有一个对象C++ 友元说明符的范围限制是什么,c++,c++11,design-patterns,proxy,friend,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;
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\u proxy()
方法返回对象的部分。从技术上讲,谁调用move构造函数,将对象从方法体移动到临时对象,即该方法的返回值?标准是否说它是在X的范围内完成的,所以friend
说明符在这里正确工作
它使用GCC 4.7-4.9和clang 3.0-3.5编译时既没有警告也没有错误。但我只需要第三方的确认,这在未来不会改变,因为这是一种标准化的行为
注意:这个代码示例可能看起来很傻,但它是一个精简的通用示例。在现实世界中,应用程序代理用于公开X的一些内部数据,而不是对X的引用
注意:这里我使用move构造函数,因为这是一个未来,是时候继续前进,忘记旧的标准了。但是这个代理可以用一个复制构造函数代替。尽管这并没有改变问题。除非在c++03和c++11/14之间,此范围内的情况发生了变化。请考虑此常规函数定义:
struct T { /* ... */ }; // to be sure that "T" is an object type
T foo()
{
T x(1, 2, 3);
return x;
}
函数foo
返回类型为T
的PR值。现在函数求值foo()
正式包含两个构造函数:首先构造x
,然后构造返回值,返回值是从x
复制或移动构造的(取决于类型T
的详细信息)
最后,当您在其他地方将变量初始化为ta=foo()代码>,还有第三个正式构造函数调用,即从临时构造函数复制a
。(复制省略允许省略两个复制构造函数,其效果可能就像您说的ta(1,2,3);
)
在上述情况下,所有构造函数都必须在正式调用时可以访问。在我的简化示例和您的原始代码中,没有一个调用位于T
的成员函数内,因此如果构造函数是private
,那么调用站点需要是类的朋友
你的代码看起来做得很正确。@KerrekSB,是的,的确,谢谢你,现已修复。@KerrekSB,std::set
无法工作,没有operator@KerrekSB,请阅读我的评论。std::vector
和std::list
都不起作用。X::Proxy
的移动构造函数是私有的:错误:“X::Proxy”类型的字段具有私有移动构造函数,您是对的。不要介意。泄漏的一种方法是auto&&x=x()
,但是您可以通过左值限定get\u proxy
成员来解决这个问题。@KerrekSB,是的,这是可以做到的。但是它是可以接受的,因为它不能将Proxy
生存期扩展到调用X::get_Proxy
的范围之外。你看,问题是我不确定,然后是返回值的构造,它是从X构造的复制或移动(取决于类型T的细节)从foo()
的主体中正式调用,以及标准是否明确定义了它。