C ++:关于使用Stroustrup示例在工会中新放置的问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C ++:关于使用Stroustrup示例在工会中新放置的问题相关的知识,希望对你有一定的参考价值。

我正在使用来自Stroustrup C ++ 4th Ed的以下示例。 Page 218.我的问题是关于析构函数。

问题:当我了解并集大小固定为最大成员时,位置new(&s) string{ss}如何为新字符串分配空间? string s不是0元素字符串吗?如果是这样,如果联合中没有足够的空间,那么placement new将如何创建一个更大的字符串?

#include <iostream>
#include <string>
using namespace std;

class Entry2 { // two alternative representations represented as a union
private:
    enum class Tag { number, text };
    Tag type; // discriminant
    union { // representation
        int i;
        string s; // string has default constructor, copy operations, and destructor
    };
public:
    struct Bad_entry { }; // used for exceptions
    string name;
    Entry2(int n) : type{Tag::number}, i{n} { };
    Entry2(string ss) : type{Tag::number} { new(&s) string{ss}; };
    ~Entry2();
    Entry2& operator=(const Entry2&); Entry2(const Entry2&);
// ...
    int number() const; string text() const;
    void set_number(int n);
    void set_text(const string&); // ...
};

Entry2::~Entry2()
{
    if (type==Tag::text)
        s.~string();
}

int Entry2::number() const
{
    if (type!=Tag::number) throw Bad_entry{};
    return i;
}

string Entry2::text() const
{
    if (type!=Tag::text) throw Bad_entry{};
    return s;
}

void Entry2::set_number(int n)
{
    if (type==Tag::text) {
        s.~string(); 
        type = Tag::number;
    }
    i = n;
}

void Entry2::set_text(const string& ss)
{
    if (type==Tag::text)
        s = ss;
    else {
        new(&s) string{ss};
        type = Tag::text;
    }
}

Entry2& Entry2::operator=(const Entry2& e)
{
    if (type==Tag::text && e.type==Tag::text) {
        s = e.s; // usual string assignment
        return *this;
    }

    if (type==Tag::text)
        s.~string(); // explicit destroy (§11.2.4)

    switch (e.type) {
    case Tag::number:
        i = e.i;
        break;
    case Tag::text:
        new(&s) string{e.s};
        type = e.type;
    }

    return *this;
}

int main(int argc, char *argv[])
{
    Entry2 e0(0);

    cout << e0.number() << endl;
    try {
        e0.text();
    } catch (...) {
        cout << "caught except" << endl;
    }

    e0.set_text("abcd");
    cout << e0.text() << endl;

    return 0;
}
答案

不,析构函数不应该总是这样做。请记住,在union中,任一时间实际上只有一个字段处于活动状态。如果std::stringunion成员未处于活动状态,则调用其析构函数将是一件不好的事情(导致未定义的行为),因为那里没有要销毁的字符串。相反,我们仅在先前某个时间点在此std::string成员上激活了析构函数的情况下才调用该析构函数。

希望这会有所帮助!

以上是关于C ++:关于使用Stroustrup示例在工会中新放置的问题的主要内容,如果未能解决你的问题,请参考以下文章

NFS 文件在 C 代码中打开

在 C/C++ 中使用 swift 库?

在 CodeBlocks 中查看语言 (C/C++) 参考/文档

我们应该在 C 中使用 exit() 吗?

在 PostgreSQL 中使用 ASSERT 的示例

关于C语言中变量在两个.C文件中的调用问题