简体   繁体   English

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

[英]C++ | temporary pointers lifetime

I'm studying C++ and in all my "experiments" i'm trying to understand temporary objects (rvalues) lifetime.我正在研究 C++ 并且在我所有的“实验”中,我试图了解临时对象(右值)的生命周期。

My question is:我的问题是:

Having an object which contains a const char* pointer, what happens when i want to use a constructor which takes "const char*" as argument?拥有一个包含 const char* 指针的 object,当我想使用以“const char*”作为参数的构造函数时会发生什么? Usually temporary objects get destructed automatically but what happens with pointers created in this way?通常临时对象会自动销毁,但是以这种方式创建的指针会发生什么?

I'm not using std::string or other c++11 classes for now because I'm just focusing on understanding rvalueness.我暂时不使用 std::string 或其他 c++11 类,因为我只专注于理解右值。

An example below:下面的一个例子:

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;
}

Usually temporary objects get destructed automatically but what happens with pointers created in this way?通常临时对象会自动销毁,但是以这种方式创建的指针会发生什么?

Pointers are objects themselves.指针本身就是对象。 Same thing happens to temporary pointer objects as happens to all other temporary objects.与所有其他临时对象一样,临时指针对象也会发生同样的事情。

Your example deletes a pointer pointing to a string literal, so the behaviour of the program is undefined.您的示例删除了指向字符串文字的指针,因此程序的行为未定义。 The class would also have a broken assignement operators even if it was used correctly by passing pointer to an array allocated with new[] . class 也会有一个损坏的赋值运算符,即使它通过将指针传递给使用new[]分配的数组来正确使用。

As for rvalueness, the only rvalue expression in the example that I could find is nullptr .至于右值,我能找到的示例中唯一的右值表达式是nullptr

Note this answer is based on a previous edit of the question where MyAwesomeClass was a String class.请注意,此答案基于对问题的先前编辑,其中MyAwesomeClassString class。

Your String class is not really a string class as it doesn't own the underlying string data.您的String class 并不是真正的字符串 class 因为它不拥有基础字符串数据。 It's more akin to std::string_view .它更类似于std::string_view

You have two avenues I can see you can pursue:我可以看到你有两种途径可以追求:

  1. Your class owns the underlying data.您的 class 拥有基础数据。 In this case the class is a wrapper around std::string and has std::string data member. Look up composition. No need to worry about lifetime as在这种情况下,class 是std::string的包装器,并且具有 std::string data member. Look up composition. No need to worry about lifetime as data member. Look up composition. No need to worry about lifetime as data member. Look up composition. No need to worry about lifetime as std::string` is well behaved. data member. Look up composition. No need to worry about lifetime as std::string` 表现良好。

  2. Your class is like a "pointer/reference/view" to another string.您的 class 就像指向另一个字符串的“指针/参考/视图”。 In this case you have a const char* and maybe std::size_t size data member.在这种情况下,您有一个const char*可能还有std::size_t大小数据成员。 You basically have a std::string_view (except for the wisdom, expertise and experience that went into designing std::string_view ).你基本上有一个std::string_view (除了设计std::string_view的智慧、专业知识和经验)。 Since you don't own the underlying data you can't do anything about the lifetime of the underlying data.由于您不拥有基础数据,因此您无法对基础数据的生命周期做任何事情。 The user of the class must make sure it doesn't end with a "YourStringView" to an expired object, just as he/she needs to make sure it doesn't end up with a reference/pointer to an expired object. class 的用户必须确保它不会以过期 object 的“YourStringView”结尾,就像他/她需要确保它不会以指向过期 ZA8CFDE6331BD49EB216Z6F96 的引用/指针结尾一样

The semantics of these two scenarios are wildly different (as the difference between an object and a pointer to an object).这两种场景的语义大相径庭(作为 object 和指向对象的指针之间的区别)。


Anyway I wouldn't recommend you do any of this except for maybe learning reasons.无论如何,我不建议您这样做,除非出于学习原因。 std::string_view already exists so just use that. std::string_view已经存在,所以只需使用它。 If you want the printing capabilities use the fmt library or the C++ format library (that is based on the mentioned fmt library).如果您想要打印功能,请使用fmt 库或 C++ 格式库(基于提到的 fmt 库)。

Even if you decide to do this for learning purposes I highly encourage you look into these alternatives and learn from how they are doing things.即使您出于学习目的决定这样做,我也强烈建议您研究这些替代方案并从它们的做事方式中学习。


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

Oh no, no, no!哦不不不不! No!!不!!

Please look into RAII and rule of 0/3/5 .请查看RAII0/3/5的规则。 Your class either owns the pointed object or it doesn't.您的 class 要么拥有尖锐的 object,要么不拥有。 If it owns it then it is responsible for creating it and deleting it.如果它拥有它,那么它负责创建和删除它。 If it doesn't then it can't do either.如果没有,那么它也做不到。 You can't have "half of responsibilities" where you are responsible for deleting it but not for creating it.你不能有“一半的责任”,你负责删除它但不负责创建它。

In user code you should never need to manually manage memory.在用户代码中,您永远不需要手动管理 memory。 Use the rule of 0.使用 0 规则。

Quick answer is that your class does not own the data, but just the raw pointer.快速回答是您的 class 不拥有数据,而只是原始指针。 Under certain conditions you will see a problem with delete operator.在某些情况下,您会看到删除运算符出现问题。 Raw pointer are not great tool to ensure correct object ownership.原始指针不是确保正确 object 所有权的好工具。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM