C++ |临时指针生命周期

问题描述

我正在学习 C++,在我所有的“实验”中,我都试图了解临时对象(右值)的生命周期。

我的问题是:

一个包含 const char* 指针的对象,当我想使用一个以“const char*”作为参数的构造函数时会发生什么?通常临时对象会自动销毁,但是以这种方式创建的指针会发生什么?

我现在不使用 std::string 或其他 c++11 类,因为我只是专注于理解右值。

以下示例:

class MyAwesomeClass {

private:
    const char* data;

public:
    MyAwesomeClass(const char* ptr) {

        this->data = ptr;
    }

    MyAwesomeClass(MyAwesomeClass&& myAwesomeClassRVALUE) {

        this->data = myAwesomeClassRVALUE.data;
        myAwesomeClassRVALUE.data = nullptr;
    }

    ~MyAwesomeClass() {

        delete data;
    }
};

int main() {

    MyAwesomeClass s = "My Awesome Class' string data.";

    return 0;
}

解决方法

通常临时对象会自动销毁,但是以这种方式创建的指针会发生什么?

指针本身就是对象。临时指针对象的情况与所有其他临时对象的情况相同。

您的示例删除了指向字符串文字的指针,因此程序的行为未定义。即使通过将指针传递给用 new[] 分配的数组来正确使用该类,它也会有一个损坏的赋值运算符。

至于右值,我能找到的示例中唯一的右值表达式是 nullptr

,

注意此答案基于之前对该问题的编辑,其中 MyAwesomeClassString 类。

您的 String 类并不是真正的字符串类,因为它不拥有底层字符串数据。它更类似于std::string_view

我认为你有两条途径可以追求:

  1. 您的班级拥有基础数据。在这种情况下,该类是 std::string 的包装器,并且 std::stringdata member. Look up composition. No need to worry about lifetime asstd::string` 表现良好。

  2. 你的类就像一个指向另一个字符串的“指针/引用/视图”。在这种情况下,您有一个 const char* 和可能 std::size_t 大小的数据成员。您基本上拥有 std::string_view(设计 std::string_view 的智慧、专业知识和经验除外)。由于您不拥有底层数据,因此您无法对底层数据的生命周期做任何事情。类的用户必须确保它不会以指向过期对象的“YourStringView”结尾,就像他/她需要确保它不会以指向过期对象的引用/指针结尾一样。>

这两种场景的语义完全不同(作为对象和指向对象的指针之间的区别)。


无论如何,除了可能出于学习原因之外,我不建议您执行任何此类操作。 std::string_view 已经存在,所以只需使用它。如果您想要打印功能,请使用 fmt library 或 C++ 格式库(基于提到的 fmt 库)。

即使您出于学习目的决定这样做,我也强烈建议您研究这些替代方案并从它们的工作方式中学习。


MyAwesomeClass(const char* ptr)
{
    this->data = ptr;
}

~MyAwesomeClass()
{
    delete data;
}

哦,不,不,不!不!!

请查看 RAII0/3/5 的规则。您的班级要么拥有指向的对象,要么不拥有。如果它拥有它,则它负责创建和删除它。如果没有,那么它也做不到。你不能有“一半的责任”,你负责删除它而不负责创建它。

在用户代码中,您应该永远需要手动管理内存。使用0的规则。

,

快速回答是您的类不拥有数据,而只是原始指针。在某些情况下,您会发现删除运算符有问题。原始指针不是确保正确对象所有权的好工具。