智能指针和异常

问题描述 投票:0回答:2

C++ primer 练习题:

确保资源被释放的一种简单方法是使用智能指针。

假设我们正在使用 C 和 C++ 都使用的网络库。使用这个库的程序可能包含如下代码:

struct connection
{
    string ip;
    int port;
    connection(string i, int p) :ip(i), port(p) {};
};  // represents what we are connecting to

struct destination
{
    string ip;
    int port;
    destination(string i, int p) :ip(i), port(p) {};
};  // information needed to use the connection

void disconnect(connection c)
{
    cout << "Scoket(" << c.port << "," << c.port << ") disconnect" << endl;
}  //close the given connection

connection connect(destination* pDest)
{
    shared_ptr<connection> pConn(new connection(pDest->ip, pDest->port), disconnect );
    cout << "Scoket(" << pConn->ip << "," << pConn->port << ") connect" << endl;
    return *pConn;
}  // open the connection


void f(destination& d)
{
    connection c = connect(&d);
}

编译错误:

error C2661: 'std::shared_ptr<connection>::shared_ptr': no overloaded function takes 2 arguments.

代码有什么问题?

c++ c++11 smart-pointers
2个回答
1
投票

来自cppreference,确实有一个需要两个参数的重载,但它并没有按照你想要的方式工作。您正在查看过载 (4)。

template< class Y, class Deleter >
shared_ptr( Y* ptr, Deleter d );

使用指定的删除器

d
作为删除器。 表达式
d(ptr)
必须格式正确,
具有明确定义的行为并且不会抛出任何异常。
d
和从中复制的存储删除器的构造不得抛出异常。

(强调我的)

请注意,删除器必须是一个可调用对象,它接受

Y*
类型的参数,即指向
std::shared_ptr
中数据的指针。所以你的
disconnect
函数,如果你打算将它用作
std::shared_ptr
的删除器,应该有签名

void disconnect(connection* c)

带有指针参数。

另请注意,正如所写,您的共享指针已经很可能表现出未定义的行为。

connection connect(destination* pDest)
{
    shared_ptr<connection> pConn(new connection(pDest->ip, pDest->port), disconnect );
    cout << "Scoket(" << pConn->ip << "," << pConn->port << ") connect" << endl;
    return *pConn;
}

让我们分解一下你在这里做了什么。首先,您创建一个指向新连接对象的共享指针。该连接对象由

std::shared_ptr
拥有和管理。当不再有
std::shared_ptr
对象指向该内存时,它将被释放,并且您的删除器将运行。然后返回底层连接(的副本)。
std::shared_ptr
是一个局部变量,理所当然地被释放,这是指向您分配的
connection*
的唯一共享指针。因此,应调用
disconnect
connect
返回后,它会返回已关闭的连接的副本。如果有人试图使用
connection
对象,它将失败,或者更糟的是,表现出未定义的行为。

如果你打算使用智能指针,你必须坚持下去。您的

connect
函数必须返回一个
std::shared_ptr<connection>
,然后由调用者管理。如果你返回的只是一个原始指针,那么构建一个共享指针是没有用的。


0
投票

你给你的

std::shared_ptr
的删除器需要接受一个与
shared_ptr
管理的相同类型的指针。所以对于一个
std::shared_ptr<connection>
,删除者需要接受一个
connection*
,但这不是
disconnect
接受的。签名不匹配,程序编译失败。

值得注意的是,您的示例中还有其他几个问题。

disconnect
没有
delete
传递给它的对象,所以
pConn
管理的对象会泄漏。此外,
connect
返回
pConn
指向的对象的副本,因此根本没有理由使用
std::shared_ptr
或动态分配。

© www.soinside.com 2019 - 2024. All rights reserved.