在我正在设计的库中,我有时需要对类的大型成员变量进行读访问。由于它们的大小,我不想通过复制成员来制作返回的getter。我不希望它们可以从外部修改,所以我不能将它们公开或返回对它们的引用。所以我想我会用一个“读者”:
class TestClass
{
public:
explicit TestClass(double d): d_(d){}
const double& readD() const { return d_; }
private:
double d_;
};
(这不是真正意味着双打)
但是这里有人可以const_cast引用并直接访问数据。即使没有假设恶意,有人也可以安全地引用数据成员并在原始对象超出范围后保留它。我知道const引用可以保持临时可行,但这并不会删除const_cast问题。 所以我想出了一个解决方法:
#include <iostream>
template<class T>
class SafeMemberReference
{
public:
using type = T;
SafeMemberReference(const T& t) :t(t) {}
explicit SafeMemberReference(T&& t) = delete;
operator const T& () && {return t; }
T get() && {return t; }
private:
const T& t;
};
class TestClass
{
public:
explicit TestClass(double d): d_(d){}
SafeMemberReference<double> readD() const { return d_; }
private:
double d_;
};
int main()
{
TestClass foo(1.2);
// temporary from read can be used as temporary in expressions
std::cout << foo.readD() << std::endl;
// temporary can be used to copy from
auto x = foo.readD().get();
// lvalue can not be used, so a possible dangling reference is no problem
auto ref = foo.readD();
//std::cout << ref << std::endl;
}
我有几个问题:
Q1)效率POV的必要性如何?我要回的最大的物体是密集的复杂矩阵,尺寸可能是1000x1000。这些副本可能经常发生
Q2)我对const&amp; amp;有效?
问题3)这看起来是一个很好的解决方案吗?它有哪些缺点?
答案 0 :(得分:4)
任何试图与语言作斗争的解决方案都不是一个好的解决方案。
如果他们以这种方式使用const_cast
,他们应该对指关节进行包装:尝试通过const_cast
对最初声明为{{1}的对象更改对象的行为未定义。即使你设法想出一个解决方案来防止这种情况,一个敌对的程序员仍然可以获取你的对象的地址,偏移该地址(使用const
指针算术)并通过该指针修改数据成员!
所以,如果我是你,我就不会对抗这种语言。根据您的原始建议,如果我是您,请返回unsigned char*
参考。
代码静态分析工具/编译器警告/代码审查/人力资源部门将帮助您保持其他协作程序员的直接和狭窄。