是否支持从 unique_ptr 到原始指针的隐式转换?

Mar*_*377 5 c++ arrays standards smart-pointers implicit-conversion

我正在阅读《Effective C++ 第三版》。在第 70 页,作者说道:

与几乎所有智能指针类一样,tr1::shared_ptrauto_ptr重载指针解引用运算符(operator->operator*),这允许隐式转换为底层原始指针(...)

然后,他展示了一个示例(当时shared_ptr是其中的一部分),该示例具有基于名为 的类的隐式转换:tr1Investment

shared_ptr<Investment> pi1();
bool taxable1 = !(pi1->isTaxFree());
                    ^implicit conversion

shared_ptr<Investment> pi2();
bool taxable2 = !((*pi2).isTaxFree());
                    ^implicit conversion
Run Code Online (Sandbox Code Playgroud)

好吧,从那时起我就写了一些测试用例,并且unique_ptr它们是有效的。

我还发现了有关unique_ptr支持数组的信息,并且shared_ptr也将继续(请参阅注释)。但是,在我的测试中,隐式转换似乎不适用于数组周围的智能指针。

示例:我希望这是有效的......

unique_ptr<int[]> test(new int[1]);

(*test)[0] = 5;
Run Code Online (Sandbox Code Playgroud)

但根据我的编译器(Visual C++ 2015 Update 3),事实并非如此。

然后,通过一点研究,我发现一些证据表明根本不支持隐式转换......例如:https: //herbsutter.com/2012/06/21/reader-qa-why-不要隐式转换为现代智能指针

此时我很怀疑。它是否支持标准) ?


注意:这本书在这个主题上可能有点过时,因为作者还在第 65 页上说“没有任何类似auto_ptrtr1::shared_ptr用于动态分配数组的东西,即使在 TR1 中也没有”。

Sto*_*ica 5

嗯,事情是这样的。没有到底层指针的隐式转换,您必须调用特定的get成员函数(这是标准库中的一个主题,想想std::string::c_str)。

但这是一件好事!隐式转换指针可能会破坏 的保证unique_ptr。考虑以下:

std::unique_ptr<int> p1(new int);
std::unique_ptr<int> p2(p1);
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,编译器可以尝试将p1s pointee 传递给p2! (它不会,因为这个调用无论如何都会有歧义,但假设它不是)。他们都会呼吁delete它!

但我们仍然希望像原始指针一样使用智能指针。因此所有的操作符都超载了。


现在让我们考虑一下您的代码:

(*test)[0] = 5;
Run Code Online (Sandbox Code Playgroud)

它调用unique_ptr::operator*which 产生int&1。然后您尝试对其使用下标运算符。那是你的错误。
如果您有一个std::unique_ptr<int[]>不仅仅是使用operator[]句柄提供的重载:

test[0] = 5;
Run Code Online (Sandbox Code Playgroud)

1正如David Scarlett指出的那样,它甚至不应该编译。数组版本不应该有这个运算符。