通过非智能指针参数将智能指针传递给函数

时间:2021-04-29 11:11:13

标签: c++ c++11 smart-pointers

考虑以下函数:

void example(void **ptr){
    std::cout << *ptr << "\n";                   // pointer value
    std::cout << ptr << "\n";                    // pointer address
    std::cout << **reinterpret_cast<int**>(ptr); // value
}

函数签名无法更改

以下代码是否有效,还是应该使用原始指针?

int main() 
{
    std::unique_ptr<int> x = std::make_unique<int>(20);
    std::cout << x.get() << "\n";                 // pointer value
    std::cout << &x << "\n";                      // pointer address
    example(reinterpret_cast<void**>(&x));
}

Live sample

2 个答案:

答案 0 :(得分:3)

它无效并且具有未定义的行为。
(如果它看起来有效,那是因为您的特定实现碰巧将 unique_ptr 的底层指针存储为它在这种特定情况下的第一个成员。不过,它仍然是 100% 纯晶莹剔透的未定义行为。)< /p>

如果你不能改变函数,你需要给它传递一些实际上是 int** - &xstd::unique_ptr<int>* 的东西,并且再多的转换也不能使一个有效的int** 来自它。
(我发现将智能“指针”视为指针通常是错误的。)

在智能“指针”中获取指向底层对象的指针的方法是通过get()

int* p = x.get();

然后你可以传递一个指向 p 的指针(不过你仍然需要转换它):

example(reinterpret_cast<void**>(&p));

答案 1 :(得分:1)

通常只有 void * 在玩带有演员表的有趣游戏时具有特殊的权利和特权。但是,考虑到您必须处理的情况:

example(reinterpret_cast<void**>(&x));

请注意,您正在传递 &x 并使用 reinterpret_cast 对其进行清洗。在 example() 中,您应该完全相反:

void example(void **ptr)
{
    auto x_ptr = reinterpret_cast<std::unique_ptr<int> *>(ptr);

现在您有一个 std::unique_ptr<int> * 可以使用。你可以按照你原来的计划进行。如果您愿意,下一步可以是:

auto &x=*xptr;

并且这个 x 与您的 x 中的 main 相同,用于所有实际目的(并且确实如此)。

相关问题