2017-03-16 51 views
1

在我设计的库中,我有时需要读取类的大型成员变量。由于它们的大小,我不想通过复制成员来获得返回的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 &有效恢复的担忧?

Q3)这似乎是一个很好的解决方案吗?它有什么缺点?

+1

SafeMemberReference'解决了什么问题?它既没有解决悬空引用的问题,也没有避免不必要的副本,也没有使用'const_cast'来阻止修改。也可以直接返回一个副本或'const&'。 – nwp

+0

你有数据可以使用。你有一个封装它的类。为什么不实施所有需要的数据操作作为这个类的方法?没有直接访问数据。 – KonstantinL

回答

4

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

他们应该得到一个包裹上的关节,如果他们以这种方式使用的const_cast:行为上试图改变原先被宣布为对象通过const_cast一个对象作为const不确定。即使你设法想出一个解决方案来防止这种情况发生,一个恶意的程序员仍然可以获取你的对象的地址,抵消该地址(使用指针算术),并通过该指针修改数据成员!

所以,如果我是你,我不会对抗这种语言。根据您的原始建议,如果我是您,请返回const参考。

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

+0

有关'const_cast'何时可用的更多信息,您可能需要阅读[cpp-reference](http://en.cppreference.com/w/cpp/language/const_cast),一个问题[“我应该何时使用...?“](http://stackoverflow.com/questions/332030/when-should-static-cast-dynamic-cast-const-cast-and-reinterpret-cast-be-used)和一个问题[ “是const_cast安全吗?”](http://stackoverflow.com/questions/357600/is-const-cast-safe)。 – TobiMcNamobi

+0

出于好奇:在OP的情况下,这真的是未定义的行为? [是const_cast安全吗?](http://stackoverflow.com/q/357600/1683161)说,如果原始对象是非常量(这是OP的'd_'),'const_cast'是安全的。 – rainer