boost ::任何类型更改导致非法访问

Ale*_*x C 5 c++ boost shared-ptr

在通过boost cpp库测试示例时,我注意到更改存储在boost :: any变量中的类型可能会导致非法访问而不是异常:

好:

boost::any a = 1;
bool *p = boost::any_cast<bool>(&a); // ok, bad cast exception
Run Code Online (Sandbox Code Playgroud)

坏:

boost::any a = std::string { "Boost" };
a = 1;
bool *p = boost::any_cast<bool>(&a); // no exception thrown
std::cout << std::boolalpha << *p << '\n'; // illegal access
Run Code Online (Sandbox Code Playgroud)

因此,我的问题是:这是一个看似错误的错误,还是与模板使用相关的一些潜在事实,我不知道?

Ami*_*ory 6

我对文档的理解不同:

返回:如果传递了指针,如果成功则返回一个类似限定值的内容,否则返回null.如果T是ValueType,则返回保持值的副本,否则,如果T是对(可能是const限定的)ValueType的引用,则返回对保持值的引用.

抛出:任何指针的重载都不会抛出; 如果不成功,带有任何值或引用的重载会抛出bad_any_cast.

所以:

  1. 转换的成功或失败取决于存储的类型和目标类型.

  2. 然而,失败的表现取决于你是否传递指针any_cast.如果传递指针,则表现形式为nullptr; 否则,表现是例外.

考虑例如这段代码:

#include <boost/any.hpp>
#include <iostream>

int main() {
    boost::any a = 1;
Run Code Online (Sandbox Code Playgroud)

这似乎与你的问题中的陈述相矛盾 - 因为它需要一个指针,它不会抛出,但指针是nullptr:

    bool *p = boost::any_cast<bool>(&a); 
    // Prints true
    std::cout << std::boolalpha << (p == nullptr) << std::endl;
Run Code Online (Sandbox Code Playgroud)

这是它看起来没问题的样子:

    int *q = boost::any_cast<int>(&a); 
    // Prints false
    std::cout << std::boolalpha << (q == nullptr) << std::endl;
Run Code Online (Sandbox Code Playgroud)

抛出,因为它没有指针:

    try {
        boost::any_cast<bool>(a);
    }
    catch(...) {
        std::cout << "caught" << std::endl;
    }
Run Code Online (Sandbox Code Playgroud)

对于字符串存储类型也是如此:

    a = std::string { "Boost" }; 
    p = boost::any_cast<bool>(&a); 
    // Prints true
    std::cout << std::boolalpha << (p == nullptr) << std::endl;
    try {
        boost::any_cast<bool>(a);
    }
    catch(...) {
        std::cout << "caught again" << std::endl;
    }
}
Run Code Online (Sandbox Code Playgroud)