我只是从一个智能指针中无意中找到了一个强制转换,并希望检查static_cast
是否可以在编译时断言以下内容是荒谬的:
int main()
{
char foobar[4] = "Foo";
std::unique_ptr<char[]> myptr = static_cast<decltype(myptr)>(foobar);
myptr.reset();
return 0;
}
这里发生的是myptr
试图释放foobar
。
我不是在问什么是智能指针,也不是问如何分配或以其他方式解决上述问题。
我认为这个问题应该在编译时发现,因为这些类型应该是完全不兼容的。
为什么在编译时没有检测到这一点?
发布于 2017-06-20 12:37:30
static_cast
将调用std::unique_ptr
的构造函数,类似于您在下面的示例中所看到的
#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中
explicit unique_ptr( pointer p ) noexcept;
在这里,您可以得到指向数组的unique_ptr
。
然后,当您调用reset()
时,unique_ptr
尝试删除具有自动生存期的变量,并导致未定义的行为。但是,编译器不需要检测到这一点。
发布于 2017-06-20 12:34:31
代码没有意义,但语法是有效的,为什么不呢?
这里的static_cast
基本上与以下内容相同:
std::unique_ptr<char[]> myptr = std::unique_ptr<char[]>(foobar);
尽管这是荒谬的,因为您不应该传递指向具有自动生存期的变量的指针,但这并不会使语法无效。static_cast
本身是非常好的。
这些类型并不不兼容,编译器也无法检查传递给static_cast
的指针是否指向动态分配的内存,因此它编译得很好。当然,正如您已经说过的,这是非常没有定义的行为,因此这个程序的结果是无法解释的,但这不是编译器的工作,提醒程序员注意。
https://stackoverflow.com/questions/44653111
复制相似问题