安全返回对成员变量的引用

til*_*llh 2 c++ templates

在我正在设计的库中,我有时需要对类的大型成员变量进行读取访问。由于它们的大小,我不想创建一个通过复制成员来返回的 getter。我不希望它们可以从外部修改,所以我不能将它们公开或返回对它们的引用。所以我想我会使用“阅读器”:

class TestClass
{
public:
    explicit TestClass(double d): d_(d){}

    const double& readD() const { return d_; }

private:
    double d_;
};
Run Code Online (Sandbox Code Playgroud)

(这并不是真正适合双打的)

但这里有人可以 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;
 }
Run Code Online (Sandbox Code Playgroud)

对此我有几个疑问:

Q1) 从效率角度来看,这有多大必要?我返回的最大对象是密集的复杂矩阵,尺寸可能为 1000x1000。这些副本可能经常发生

Q2)我对 const& 返回的担忧是否有效?

Q3)这看起来是一个好的解决方案吗?它有哪些缺点?

Bat*_*eba 5

任何试图对抗语言本身的解决方案都不是一个好的解决方案。

如果他们以这种方式使用 a ,他们应该感到紧张const_cast:尝试通过最初声明为 undefined 的对象上的 a 来更改对象const_cast行为。即使您设法想出一个解决方案来防止这种情况,恶意程序员仍然可以获取您的对象的地址,偏移该地址(使用指针算术)并通过该指针修改数据成员!constunsigned char*

所以如果我是你我就不会对抗语言。const如果我是您,请根据您最初的建议返回参考信息。

代码静态分析工具/编译器警告/代码审查/人力资源部门将帮助您让其他协作程序员保持正直和狭窄。