堆上的字符串对象需要C ++智能指针吗?

时间:2016-06-16 06:49:14

标签: c++11 memory-leaks heap shared-ptr

我试图证明我的问题。我不能提供一个完整的例子,但我认为我的问题很清楚。

我有这个构造函数:

mlt::Client::Client(const string& hostname, struct sockaddr *hostaddr)
        : content(nullptr),
          hostname(hostname),
          ip_and_port(mlt::Client::prepareIPandPort(hostaddr))
{ /* ... */ }

如您所见,我使用了一个转换hostaddr的静态函数:

#include <iostream>
#include <libnet.h>

const string& mlt::Client::prepareIPandPort(struct sockaddr *hostaddr) {
    assert(hostaddr != nullptr);

    string *ipport;
    char clienthost[NI_MAXHOST];
    char clientport[NI_MAXSERV];
    int result = getnameinfo(hostaddr, sizeof(*hostaddr),
                             clienthost, sizeof(clienthost),
                             clientport, sizeof(clientport),
                             NI_NUMERICHOST | NI_NUMERICSERV);

    if (result != 0) {
        cerr << "Error: " << gai_strerror(result) << endl;
        ipport = new string {"unknown"};
    }
    else {
        switch (hostaddr->sa_family) {
            case AF_INET:
                ipport = new string {string(clienthost) + ":"
                                     + string(clientport)};
                break;
            case AF_INET6:
                ipport = new string {"[" + string(clienthost) + "]:"
                                     + string(clientport)};
                break;
            default:
                ipport = new string {"unknown"};
        }
    }

    return *ipport;
}

mlt :: Client :: ip_and_port声明为:

const string ip_and_port;

根据我的理解,我在堆上创建一个字符串,并将取消引用的内容作为对const字符串的引用返回。此结果在初始化程序中用于初始化const字符串成员ip_and_port。

这会产生内存泄漏吗?如果我打电话&#34;删除some_client_instance&#34;会发生什么?和析构函数mlt :: Client ::〜Client()被调用?

我是否必须在mlt :: Client :: prepareIPandPort中使用智能指针(std :: shared_ptr)?如果是这样,这段代码怎么样?

非常感谢

1 个答案:

答案 0 :(得分:0)

是的,这会导致内存泄漏。您需要在功能结束时致电delete some_client_instance

理想情况下,你应该:

  • mlt::Client::prepareIPandPort
  • 中返回一个纯字符串(不是引用)
  • ip_and_port
  • 使用纯字符串
  • 初始化ip_and_port,如下所示

这样,字符串只会创建一次,永远不会被复制。

mlt::Client::Client(const string & hostname, struct sockaddr *hostaddr)
        : content(nullptr),
          hostname(hostname),
          ip_and_port(std::move(mlt::Client::prepareIPandPort(hostaddr)))
{ /* ... */ }