C++ 是否可以将常量引用返回给私有成员?

C++ 是否可以将常量引用返回给私有成员?,c++,reference,constants,C++,Reference,Constants,我需要实现对私有成员容器的只读访问。如果我返回一个常量引用,是否可以对其进行const_cast并获得对该成员的完全访问权限?使用什么技术 谢谢。将常量引用返回给私人成员是否安全 const int &ref = your_object.your_function(); *(int*)&ref = 1234; 是,只要引用的生存期不超过返回它的对象的生存期。如果必须公开不希望修改的私有成员,这是一种很好的方法。这不是万无一失的,但在C语言中这是一种更好的方法++ 是否有可能使用

我需要实现对私有成员容器的只读访问。如果我返回一个常量引用,是否可以对其进行const_cast并获得对该成员的完全访问权限?使用什么技术

谢谢。

将常量引用返回给私人成员是否安全
const int &ref = your_object.your_function();
*(int*)&ref = 1234;
是,只要引用的生存期不超过返回它的对象的生存期。如果必须公开不希望修改的私有成员,这是一种很好的方法。这不是万无一失的,但在C语言中这是一种更好的方法++

是否有可能使用const_cast来实际地干扰成员 是的,你无法阻止这种情况。在任何时候,没有办法阻止某人在C++中丢弃const。这是C++的一个限制/特性。p>
不过,一般来说,您应该将const_cast的每次使用都标记为bug,除非它包含足够详细的注释,说明为什么有必要这样做

是的,所以这可能不是你想做的。另一方面,如果有人要麻烦您强制转换引用,他们可能真的知道自己在做什么。

const\u cast绝对可以用来获得对该成员的完全访问权。我想如果人们下定决心要开枪打自己的脚,你就无法阻止他们。如果私有成员不重,则考虑返回该变量的副本。

可以获得完全访问。但是为什么呢

别忘了让访问者保持常量正确

const MyType& getMyValue() const;
还可以在回调中注入私有值

void doJob( callback c )
{
    c( myPrivateValue_ );
}

返回常量&在许多情况下都是明智的做法,尤其是当返回的对象很大或无法复制时


关于COSTYSTCAST,请记住C++中的“私有”访问说明符是帮助程序员的,它不是安全措施。如果有人想要访问对象的私有成员,它可以获取这些成员,不管你如何阻止它。

不要担心用户进行常量转换只是为了破坏你的不变量。如果他们真的想破坏你的代码,他们可以不用你提供内部属性的访问器。通过返回一个常量引用,普通用户不会错误地修改您的数据

如果恶意代码编写者真的关心并了解环境(编译器),他们无论如何都可以破坏它。常量在编译过程中丢失(在我所知道的所有编译器中)。一旦编译单元转换成二进制对象,这些对象就不知道常量,可以利用它来利用它

// a.h
class A
{
public:
   A( int a ) : data_( a ) {}
   int get() const { return data_; }
private:
   int data_;
};

// malicious.h
class A;
void change( A& a, int new_value );

// malicious.cpp
//     does not include a.h, but redefines an almost exact copy of it
class A {
public:
   A( int a ) : data_( a ) {}
   int get() const { return data_; }
   int data_; // private removed
};
void change( A& a, int new_value )
{
   a.data_ = new_value;
}

// main.cpp
#include "a.h"
#include "malicious.h"
int main()
{
   A a(0);
   change( a, 10 );
   std::cout << a.get() << std::endl; // 10
}
//a.h
甲级
{
公众:
A(inta):数据{(A)}
int get()常量{返回数据}
私人:
int数据;
};
//恶意的
甲级;
无效变更(A&A、int新值);
//恶意的.cpp
//不包括a.h,但重新定义了几乎完全相同的副本
甲级{
公众:
A(inta):数据{(A)}
int get()常量{返回数据}
int data;//私有已删除
};
无效更改(A&A,整数新值)
{
a、 数据=新值;
}
//main.cpp
#包括“a.h”
#包括“恶意.h”
int main()
{
A(0);
更改(a,10);

我认为赫伯·萨特曾经说过,一个人应该“防范墨菲,而不是马基雅维利”。也就是说,你应该尽一切可能防止代码被意外错误使用,但对于人们故意滥用代码,你无能为力

如果有人真的想破坏你的代码,他们可以,即使是通过
#定义private-public
,然后再包含你的头(从而造成ODR冲突,但我离题了)


因此,是的,传回常数参考是可以的。

根据Scott Meyer的书(见第28项),你应该避免它。以下是第28项的摘录:

这就是为什么任何函数都会将句柄返回到 这个物体是危险的,把手是不是有点危险无关紧要 指针、引用或迭代器。它是否为 使用const限定。成员函数是否 返回句柄本身就是常量。重要的是 正在返回句柄,因为一旦完成,您将运行 句柄比它所引用的对象寿命长的风险


我相信const_cast操作员是做意外动作的首选方式。天哪!为什么会有反对票?莫里斯所做的只是证明常规的C型演员足以“打破”constness——你真的认为邪恶的罪犯Jack担心样式问题吗?这不是未定义的行为吗?@AMA这取决于函数返回的内容。如果它是对对象中int字段的引用,那么这段代码会将该字段的值更改为1234。一般来说,生存期不是问题。如果你没有对于引用,您将按值返回,即临时的。它有自己的生存期问题,这非常类似。引用的生存期问题与临时的问题有很大不同。引用可能会在没有警告的情况下变得无效。对于临时的,您知道它何时超出范围——如果您阅读了标准非常接近!;-)我不得不处理一个Get方法为非常量的类。这太糟糕了。我所做的仍然是将ptr返回到const,并丢弃const以调用Get函数,并评论说“这个蹩脚的类应该使其GetFoo方法为常量,以使我们停止丢弃const”绝对同意你对const_cast的看法。@JohannesSchaub litb:这就是传染性const,这是一个单独的问题。标记其getter
const
的库不会造成伤害。一个经常使用
const
的应用程序,但依赖于另一个不遵循相同
const
c的较低级别库更新,将需要在应用程序上进行更多的工作