首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么static_cast可以将原始指针编译为智能指针

为什么static_cast可以将原始指针编译为智能指针
EN

Stack Overflow用户
提问于 2017-06-20 12:29:00
回答 2查看 1.3K关注 0票数 3

我只是从一个智能指针中无意中找到了一个强制转换,并希望检查static_cast是否可以在编译时断言以下内容是荒谬的:

代码语言:javascript
运行
复制
int main()
{
    char foobar[4] = "Foo";
    std::unique_ptr<char[]> myptr = static_cast<decltype(myptr)>(foobar);
    myptr.reset();
    return 0;
}

这里发生的是myptr试图释放foobar

我不是在问什么是智能指针,也不是问如何分配或以其他方式解决上述问题。

我认为这个问题应该在编译时发现,因为这些类型应该是完全不兼容的。

为什么在编译时没有检测到这一点?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-06-20 12:37:30

static_cast将调用std::unique_ptr的构造函数,类似于您在下面的示例中所看到的

代码语言:javascript
运行
复制
#include <iostream>
#include <memory>

using std::cout;
using std::endl;

class Something {
public:
    explicit Something(int) {
        cout << __PRETTY_FUNCTION__ << endl;
    }
};

int main() {
    auto something = static_cast<Something>(1);
    (void) something;
}

如果您想知道为什么static_cast会导致对std::unique_ptr的构造函数的调用,那么可以用标准中的以下引号来解释它(强调我的)

静态铸造 expr.static.cast/4

如果声明是格式良好的E 229,则可以使用表单T static_cast 将表达式e显式转换为 T t(e); 类型,对于某些已发明的临时变量t (8.5)。这种显式转换的效果与执行声明和初始化,然后使用临时变量作为转换的结果相同。表达式e被用作glvalue当且仅当初始化时使用它作为lvalue。

因此,基本上在您的示例中,数组被视为unique_ptr构造函数的参数,然后使用假想的临时值初始化变量myptr (在大多数情况下使用省略)。

在您的示例中调用的构造函数是(2),它位于下面的cppreference页面ptr

代码语言:javascript
运行
复制
explicit unique_ptr( pointer p ) noexcept;

在这里,您可以得到指向数组的unique_ptr

然后,当您调用reset()时,unique_ptr尝试删除具有自动生存期的变量,并导致未定义的行为。但是,编译器不需要检测到这一点。

票数 7
EN

Stack Overflow用户

发布于 2017-06-20 12:34:31

代码没有意义,但语法是有效的,为什么不呢?

这里的static_cast基本上与以下内容相同:

代码语言:javascript
运行
复制
std::unique_ptr<char[]> myptr = std::unique_ptr<char[]>(foobar);

尽管这是荒谬的,因为您不应该传递指向具有自动生存期的变量的指针,但这并不会使语法无效。static_cast本身是非常好的。

这些类型并不不兼容,编译器也无法检查传递给static_cast的指针是否指向动态分配的内存,因此它编译得很好。当然,正如您已经说过的,这是非常没有定义的行为,因此这个程序的结果是无法解释的,但这不是编译器的工作,提醒程序员注意。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44653111

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档