const_cast 安全吗?

发布于 2024-07-09 22:21:40 字数 297 浏览 12 评论 0原文

我找不到太多关于 const_cast 的信息。 我能找到的唯一信息(在 Stack Overflow 上)是:

const_cast<>() 用于添加/删除变量的 const(ness)(或 volatile-ness)。

这让我很紧张。 使用 const_cast 会导致意外行为吗? 如果是这样,那又怎样?

或者,什么时候可以使用const_cast?

I can't find much information on const_cast. The only info I could find (on Stack Overflow) is:

The const_cast<>() is used to add/remove const(ness) (or volatile-ness) of a variable.

This makes me nervous. Could using a const_cast cause unexpected behavior? If so, what?

Alternatively, when is it okay to use const_cast?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

旧人哭 2024-07-16 22:21:40

仅当您转换最初为非 const 的变量时,const_cast 才是安全的。 例如,如果您有一个采用 const char * 参数的函数,并且传入可修改的 char *,则 const_cast 是安全的code> 将该参数返回到 char * 并修改它。 但是,如果原始变量实际上是 const,则使用 const_cast 将导致未定义的行为。

void func(const char *param, size_t sz, bool modify)
{
    if(modify)
        strncpy(const_cast<char *>(param), sz, "new string");
    printf("param: %s\n", param);
}

...

char buffer[16];
const char *unmodifiable = "string constant";
func(buffer, sizeof(buffer), true);  // OK
func(unmodifiable, strlen(unmodifiable), false); // OK
func(unmodifiable, strlen(unmodifiable), true);  // UNDEFINED BEHAVIOR

const_cast is safe only if you're casting a variable that was originally non-const. For example, if you have a function that takes a parameter of a const char *, and you pass in a modifiable char *, it's safe to const_cast that parameter back to a char * and modify it. However, if the original variable was in fact const, then using const_cast will result in undefined behavior.

void func(const char *param, size_t sz, bool modify)
{
    if(modify)
        strncpy(const_cast<char *>(param), sz, "new string");
    printf("param: %s\n", param);
}

...

char buffer[16];
const char *unmodifiable = "string constant";
func(buffer, sizeof(buffer), true);  // OK
func(unmodifiable, strlen(unmodifiable), false); // OK
func(unmodifiable, strlen(unmodifiable), true);  // UNDEFINED BEHAVIOR
御弟哥哥 2024-07-16 22:21:40

我可以想到 const_cast 安全且有用的两种情况(可能还有其他有效情况)。

一种情况是,当您有一个 const 实例、引用或指针,并且您想要将指针或引用传递给非 const 正确的 API,但您确定不会修改该对象时。 您可以 const_cast 指针并将其传递给 API,相信它不会真正改变任何内容。 例如:

void log(char* text);   // Won't change text -- just const-incorrect

void my_func(const std::string& message)
{
    log(const_cast<char*>(&message.c_str()));
}

另一种情况是,如果您使用的是未实现“可变”的较旧编译器,并且您想要创建一个逻辑上 const 但不是按位 const 的类。 您可以在 const 方法中 const_cast 'this' 并修改类的成员。

class MyClass
{
    char cached_data[10000]; // should be mutable
    bool cache_dirty;        // should also be mutable

  public:

    char getData(int index) const
    {
        if (cache_dirty)
        {
          MyClass* thisptr = const_cast<MyClass*>(this);
          update_cache(thisptr->cached_data);
        }
        return cached_data[index];
    }
};

I can think of two situations where const_cast is safe and useful (there may be other valid cases).

One is when you have a const instance, reference, or pointer, and you want to pass a pointer or reference to an API that is not const-correct, but that you're CERTAIN won't modify the object. You can const_cast the pointer and pass it to the API, trusting that it won't really change anything. For example:

void log(char* text);   // Won't change text -- just const-incorrect

void my_func(const std::string& message)
{
    log(const_cast<char*>(&message.c_str()));
}

The other is if you're using an older compiler that doesn't implement 'mutable', and you want to create a class that is logically const but not bitwise const. You can const_cast 'this' within a const method and modify members of your class.

class MyClass
{
    char cached_data[10000]; // should be mutable
    bool cache_dirty;        // should also be mutable

  public:

    char getData(int index) const
    {
        if (cache_dirty)
        {
          MyClass* thisptr = const_cast<MyClass*>(this);
          update_cache(thisptr->cached_data);
        }
        return cached_data[index];
    }
};
浅语花开 2024-07-16 22:21:40

我很难相信这是您能找到的有关 const_cast 的唯一信息。 引用自 第二次 Google 点击

如果你抛弃了常量
已明确表示的对象
声明为 const,并尝试
修改一下,结果未定义。

但是,如果你抛弃
对象的常量性
被显式声明为 const,你
可以安全地修改它。

I find it hard to believe that that's the only information you could find about const_cast. Quoting from the second Google hit:

If you cast away the constness of an
object that has been explicitly
declared as const, and attempt to
modify it, the results are undefined.

However, if you cast away the
constness of an object that has not
been explicitly declared as const, you
can modify it safely.

瑕疵 2024-07-16 22:21:40

亚当说的话。 const_cast 有用的另一个例子:

struct sample {
    T& getT() { 
        return const_cast<T&>(static_cast<const sample*>(this)->getT()); 
    }

    const T& getT() const { 
       /* possibly much code here */
       return t; 
    }

    T t;
};

我们首先将 const 添加到 this 指向的类型,然后调用 getT 的 const 版本,然后从返回中删除 const类型,这是有效的,因为 t 必须是非常量(否则,无法调用 getT 的非常量版本)。 如果您有一个很大的函数体并且您想避免冗余代码,这会非常有用。

What Adam says. Another example where const_cast can be helpful:

struct sample {
    T& getT() { 
        return const_cast<T&>(static_cast<const sample*>(this)->getT()); 
    }

    const T& getT() const { 
       /* possibly much code here */
       return t; 
    }

    T t;
};

We first add const to the type this points to, then we call the const version of getT, and then we remove const from the return type, which is valid since t must be non-const (otherwise, the non-const version of getT couldn't have been called). This can be very useful if you got a large function body and you want to avoid redundant code.

一袭水袖舞倾城 2024-07-16 22:21:40

简短的回答是否定的,这不安全。

长的答案是,如果您足够了解如何使用它,那么它应该是安全的。

当你进行转换时,你本质上是在说:“我知道一些编译器不知道的东西。” 在 const_cast 的情况下,您所说的是,“即使此方法接受非常量引用或指针,我知道它不会更改我传递给它的参数。”

因此,如果您确实知道使用演员表时声称知道的内容,那么使用它就可以了。

The short answer is no, it's not safe.

The long answer is that if you know enough to use it, then it should be safe.

When you're casting, what you are essentially saying is, "I know something the compiler doesn't know." In the case of const_cast, what you are saying is, "Even though this method takes in a non-const reference or pointer, I know that it won't change the parameter I pass it."

So if you do actually know what you are claiming to know in using the cast, then it's fine to use it.

李不 2024-07-16 22:21:40

如果您开始修改编译器认为是 const 的内容,那么您就会破坏任何线程安全的机会。

You're destroying any chance at thread-safety, if you start modifying things that the compiler thought were const.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文