简体   繁体   English

C ++中的常量正确性问题

[英]Const Correctness Question in C++

I have a random question about const correctness. 我有一个关于const正确性的随机问题。

Lets say i have a class that is a singleton. 可以说我有一个单例课程。

class Foo : public Singleton<Foo>
{
    friend class Singleton<Foo>;

public:
    std::wstring GetOrSet(const int id) const;

private:
    Foo();
    ~Foo();
    void LoadStringIntoMap(const int id, const std::wstring &msg);

    std::map<int, std::wstring> strMap;
};

The functions are defined as such 功能定义如下

std::wstring Foo::GetOrSet(const int stringId) const
{
    if ( strMap.find(stringId) == strMap.end() )
    {
        Foo::GetInstance()->LoadStringIntoMap(stringId, std::wstring(L"HELLO WORLD222"));
    }
    std::map<int, std::wstring>::const_iterator retStr = strMap.find(stringId);
    return retStr->second;
}

void Foo::LoadStringIntoMap(const int stringId, const std::wstring &msg)
{    
    strMap.insert(std::pair<int, std::wstring>(stringId, msg));
}

If i directly get call LoadStringIntoMap i get an error that it cannot convert this pointer from const Foo to Foo &. 如果我直接接到调用LoadStringIntoMap的消息,则会收到一个错误,它无法将此指针从const Foo转换为Foo&。 Which makes sense since your calling a non const function from within a const function. 这很有意义,因为您从const函数中调用了非const函数。 But why is this not an issue when calling the singleton, and doing modification through that. 但是,为什么在调用单例并进行修改时这不是问题。

Is this just really unsafe? 这真的不安全吗?

This is what singleton is defined as: 这就是单例定义为:

   template <typename T> class Singleton
{
protected:
    Singleton () {};
    ~Singleton () {};

public:
    static T *GetInstance()
    {
        return (static_cast<T*> (m_This));
    }

    static void Destroy()
    {
        if(m_This != NULL)
            delete m_This;
    }

    static void CreateInstance()
    {
        m_This = GetInstance();

        if (m_This == NULL)
        {
           m_This = new T;
        }
    }

private:
    // Unique instance
    static T *m_This;
};

template <typename T> T *Singleton<T>::m_This = NULL;

GetInstance() returns a non- const pointer. GetInstance()返回一个非const指针。 As the function GetInstance() is not bound to the object itself, but class-wide, it may be called from a const function. 由于函数GetInstance()并不绑定到对象本身,而是绑定到整个类,因此可以从const函数中调用它。

Essentially, you have tricked yourself out of the const environment; 本质上,您已经使自己脱离了const环境; but then, you could do that from any context/state of your program (privateness of members is not bound to specific objects, only classes). 但随后,您可以在程序的任何上下文/状态下执行此操作(成员的私有性不限于特定的对象,而仅限于类)。 In this scenario, you have to care for a safe usage of the singleton accessors on your own. 在这种情况下,您必须自己保护单例访问器的安全使用。

Its not that its unsafe its just totally illogical. 不是说它不安全就是完全不合逻辑的。 If you don't want to have a constant this pointer than don't specify the function as const. 如果您不想使用该指针,则不要将函数指定为const。 Its that simple. 就这么简单。 The compiler can't do much optimisation there anyway. 无论如何,编译器在那里无法进行太多优化。

The reason it works is because the singleton passes a new this pointer NOT inherited from the parent function. 它起作用的原因是因为单例传递了一个新的this指针,该指针不是从父函数继承的。 It doesn't matter that they are both the same address .. one is const which the function can't use. 它们都是相同的地址都没关系。一个是const,函数无法使用。 One isn't 一个不是

The code illustrates that it doesn't make a lot of sense to have a const pointer to a singleton, when you can grab a non-const reference to the singleton at any time, via the global getter. 该代码说明,当您可以随时通过全局getter来获取对单例的非const引用时,拥有指向单例的const指针没有多大意义。 The global getter says, "sure, anyone at all can modify the object any time they like. That's fine". 全局获取者说:“可以肯定,任何人都可以随时修改对象。这很好。” The const member function says, "oh, no, it'd be really bad to modify this object". const成员函数说:“哦,不,修改此对象真的很糟糕”。

If the class wasn't singleton, so that it wasn't certain that this refers to the same object that GetInstance returns, then this might make perfect sense in a lot of cases. 如果该类不是单身,所以,这是不肯定的是, this指的是同一个对象GetInstance回报,那么这可能会使在很多情况下非常有意义。 Since they do refer to the same object, and everyone knows they do because it's singleton, they can't both be right. 由于它们确实引用同一对象,并且每个人都知道它们是因为它是单例的,所以他们不可能两者都是正确的。

You can't ever assume that some globally-accessible object won't be modified (at least, you can't assume the const system will help you avoid modifying it - there may be some other properties of the class which make guarantees about modifications). 您永远无法假设某些全局可访问的对象不会被修改(至少,您不能假设const系统将帮助您避免对其进行修改-该类的某些其他属性可以保证对修改进行保证)。 So either GetInstance is unsafe, or the motivations of the person calling member functions on a const Foo are unsafe, depending on who is actually correct as to whether the object should be modified in the given bit of code. 因此,要么GetInstance是不安全的,要么是在const Foo上调用成员函数的人的动机是不安全的,这取决于在对象上是否应该在给定的代码段中修改对象的人是正确的。 In this case, I'm not sure what the point is of defining any const member functions of an object which is globally modifiable - if someone has a const reference to it, then where did they get that reference from, and why? 在这种情况下,我不确定定义可全局修改的对象的任何const成员函数的意义是什么-如果有人对此有const引用,那么他们从何处获得该引用,为什么? And what makes anyone think a function called "Get OrSet " should be const in the first place? 是什么让任何人认为一个叫做“ Get OrSet ”的函数首先应该是const?

One option is for GetInstance to return const Foo& , but have some mutable member variables for the things which it's OK for anyone to modify, any time, even through a const reference. 一种选择是让GetInstance返回const Foo& ,但是具有一些mutable成员变量,以便任何人都可以随时修改,即使通过const引用也可以。 But it depends what Foo is actually for: mutable should really only be used for things like caches which don't modify the "observable" guaranteed behaviour of the object. 但这取决于Foo的实际用途: mutable实际上仅应用于不会修改对象的“可观察”保证行为的缓存之类的东西。

Yes, it's just unsafe. 是的,这是不安全的。

The tools don't have any (straightforward) way of knowing that the 'const' on Foo::GetOrSet is going to apply to the same instance of Foo as Foo::GetInstance(). 这些工具没有任何(直接)知道Foo :: GetOrSet上的'const'将与Foo :: GetInstance()应用于相同的Foo实例的方式。

'Singleton' isn't a policy which means anything to the compiler. 'Singleton'不是对编译器意味着任何意义的策略。

Because compiler cares only about access to this . 因为编译器只关心访问this It doesn't go as far as checking all the paths that can change your object. 它不会检查所有可以更改对象的路径。 So yeah, it works. 是的,它有效。 Is it unsafe? 它不安全吗? It depends :) Shouldn't be in most cases but sure there's a set of circumstances that can make it all fall over. 这取决于:)在大多数情况下不应该这样,但是请确保在某些情况下可以使其全部崩溃。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM