C++ 允许l值引用和不允许r值引用作为函数参数?
所以我有一个管理资源的类。与C++ 允许l值引用和不允许r值引用作为函数参数?,c++,c++11,rvalue-reference,C++,C++11,Rvalue Reference,所以我有一个管理资源的类。与std::mutex类似,它有acquire和release方法。为了成为一名优秀的RAII风格的程序员,我想实现模拟到std::unique_lock,以防止永远获取资源。然而,出于语义上的原因,acquire和release是const函数(相信我) 这意味着我的RAII类的构造函数有一个签名raitype(const T&)。这个问题是,一个右值也会绑定到它。我希望能从苏的脑子里找出一个阻止这种事情发生的方法 在编码方面: class ResourceType
std::mutex
类似,它有acquire
和release
方法。为了成为一名优秀的RAII风格的程序员,我想实现模拟到std::unique_lock
,以防止永远获取资源。然而,出于语义上的原因,acquire
和release
是const
函数(相信我)
这意味着我的RAII类的构造函数有一个签名raitype(const T&)
。这个问题是,一个右值也会绑定到它。我希望能从苏的脑子里找出一个阻止这种事情发生的方法
在编码方面:
class ResourceType
{
public:
void acquire() const{}
void release() const{}
};
template< class T >
class RAIIClass
{
public:
RAIIClass(const T & in_t) : t(in_t) { t.acquire(); }
~RAIIClass() { t.release(); }
private:
const T & t;
};
ResourceType foo() { return ResourceType(); }
int main()
{
ResourceType x1;
const ResourceType & x2(x1);
{
RAIIClass<ResourceType> x(x1); //Allowable
}
{
RAIIClass<ResourceType> x(x2); //Allowable
}
{
RAIIClass<ResourceType> x(foo()); //Currently allowable, would like to disallow.
}
}
类资源类型
{
公众:
void acquire()常量{}
void release()常量{}
};
模板
类RAIIClass
{
公众:
RAIIClass(const T&in_T):T(in_T){T.acquire();}
~RAIIClass(){t.release();}
私人:
康斯特T&T;
};
ResourceType foo(){return ResourceType();}
int main()
{
资源型x1;
常量资源类型&x2(x1);
{
RAIIClass x(x1);//允许
}
{
RAIIClass x(x2);//允许
}
{
RAIIClass x(foo());//当前允许,希望不允许。
}
}
有什么想法吗?添加此构造函数:
RAIIClass(const T&&) = delete;
RAIIClass(const T & in_t) : t(in_t) { t.acquire(); }
这将绑定到常量或非常量右值,其中常量和非常量左值都将首选现有构造函数:
RAIIClass(const T&&) = delete;
RAIIClass(const T & in_t) : t(in_t) { t.acquire(); }
禁止为临时对象创建管理器的另一种方法是更改管理器类,以便在使用临时()调用时在内部存储托管对象:
模板
类RAIIClass;
模板
RAIIClass make_防护装置(T&&);
模板
类RAIIClass
{
公众:
~RAIIClass(){t.release();}
私人:
朋友拉伊格拉斯(T&&);
RAIIClass(T&&in_T):T(std::forward(in_T)){T.acquire();}
T;
};
模板
RAIIClass make_防护装置(T&T){
返回{std::forward(t)};
}
ResourceType foo(){return{};}
int main()
{
资源型x1;
常量资源类型&x2(x1);
{
auto x=使保护(x1);//允许
}
{
auto x=使保护(x2);//允许
}
{
auto x=make_guard(foo());//也允许。
}
}
为什么要避免右值?另外,请注意,在这种设计中,您的RaiicClass
是不可分配的(也许这很好,但请注意!)。立即解决方案:RaiicClass(T&&)=delete
但我不相信这不是xy问题。@juanchopanza由于专有原因,我无法真正了解它,但它们在语义上是常量,内部有一个可变变量。你必须相信我,这在实际问题中是有意义的。@OliverCharlesworth RAIIClass的析构函数会调用一个无效的ref,如果参数是一个临时的Yup,正如上面所建议的,但你似乎是最快实际键入它作为答案的人。谢谢。+1:这里的诀窍是有一个工厂推导的函数,它接受T&&
,一个构造函数接受T&&
,然后在实例中存储T
:这是一种常见模式。如果T&&
是临时右值,则T
是值类型,否则它是引用类型。在RaiicClass
中明确地阻止操作符=
和复制构造,并明确地允许移动构造,可能是一个好主意。