rvalue析构函数何时被调用?/ 这样做是否可行?

4

以下包装类是否是使用std::unique_ptr保留中间对象以访问me成员而不复制me的“可行”方式?

以下是示例:

#include <iostream>
#include <memory>

/* myobj from another library */
class myobj {
public:
    std::string me; /* actual member of interest is larger and more 
                       complicated. Don't want to copy of me or myobj */

    /* more members in actual class */

    myobj(std::string i_am) {
        /* more stuff happens in constructor */
        me = i_am;
    }

    ~myobj(){
        std::cout << me << ": Goodbye" << std::endl;
    }
};

/* A function in another library */
void who_is_this(std::string *who){
  std::cout << "This is " << *who << std::endl;
}

/* wrapper which I define */
class myobj_wrapper {
    using obj_ptr = std::unique_ptr<myobj>;
    obj_ptr ptr;

public:
    std::string *who;

    myobj_wrapper(std::string i_am): 
        ptr(new myobj(i_am)), who(&ptr.get()->me) {}

    myobj_wrapper(myobj &the_obj): who(&the_obj.me) { }
};

int main()
{
    {
        myobj bob("Bob");
        who_is_this(myobj_wrapper(bob).who); 
    }

    who_is_this(myobj_wrapper("Alice").who);

    return 0;
}

生成的程序产生以下结果:
This is Bob
Bob: Goodbye
This is Alice
Alice: Goodbye

我定义了myobj_wrapper,用于获取多个对象的who指针。我不确定感兴趣的对象(在上面是std::string)是否会在who_is_this函数中被评估之前被销毁。从上面看来好像不会,但我应该预料到这种情况吗?上述解决方案有什么缺陷吗?


代码在我看来没问题。虽然我必须承认我不太明白这个练习的重点。我不理解这个代码是为了解决什么问题的。 - Igor Tandetnik
什么是rvalue析构函数? - Dean Seo
我指的是在 who_is_this(myobj_wrapper("Alice").who); 中动态分配的对象。 - Benjamin Christoffersen
1个回答

2

我不确定,但这是我的观点:

who_is_this(myobj_wrapper("Alice").who);

这将创建一个包装对象,该对象将以字符串文字作为其参数。然后,将动态创建一个myobj实例,并将其移交给唯一指针。通过该实例,我们获取其数据(字符串),并从包装类中创建传统指针指向它。所以,现在who指向me,即Alice。
我们将who(一个指针)传递给:
void who_is_this(std::string *who)

这意味着函数的参数who不是副本,而是指向原始数据的指针。

因此,整个问题在于当包装对象超出范围时(因此其数据成员(唯一指针)也会超出范围),表示已动态创建的myobj实例将被垃圾收集,这反过来意味着me也将超出范围,who也将超出范围。

在执行who_is_this()之后,包装对象将超出范围,这意味着您的代码没有问题。


“包装对象”将在who_is_this()执行后超出范围,这意味着您的代码是正确的。谢谢回答! - Benjamin Christoffersen
1
谢谢。我想有人可能会添加一个关于陷阱的评论。我猜没有。具体例子在这里,我使用了Armadillo库。请参见map_res类和例如lp_map方法。有时需要新的arma::vec,而其他时候则不需要创建新对象。(忽略类上面的注释--它是错误的)。 - Benjamin Christoffersen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接