避免在需要指针时创建命名变量

Avoid creating named variables when pointer is required

我一直在创建命名变量,以便能够将它们的地址传递给需要指针的构造函数,但我希望能够在构造函数或其他函数中创建它们,然后将它们的地址传递给需要指针的构造函数。

我正在使用 C++ 20,并且我有以下 类:

#include <iostream>
#include <string>
#include <vector>
#include <random>

using std::string, std::cout, std::cin, std::endl, std::vector;

class symbol {
public:
    enum symbolKind {
        null,
        terminal,
        sequence,
        weighted,
        random
    };
protected:
    symbolKind kind;
public:
    virtual string evaluate() const = 0;
    symbolKind getKind() {
        return kind;
    }
};

class nullSymbol : public symbol {
public:
    nullSymbol() {
        kind = symbol::null;
    }
    string evaluate() const override {
        return "";
    }
};

class terminalSymbol : public symbol {
private:
    string termString;
public:
    terminalSymbol(string pString) {
        kind = symbol::terminal;
        termString = pPhoneme;
    }
    string evaluate() const override {
        return termString;
    }
};

class sequenceSymbol : public symbol {
private:
    vector<symbol*> symArray;
public:
    sequenceSymbol(vector<symbol*> pArr) {
        kind = symbol::sequence;
        symArray = pArr;
    }
    string evaluate() const override {
        string retStr = "";
        for (symbol* current : symArray) {
            retStr += current->evaluate();
        }
        return retStr;
    }
};

class weightedSymbol : public symbol {
private:
    float weight;
    symbol* subSym;
public:
    weightedSymbol(symbol* pSym, float pWeight) {
        kind = symbol::weighted;
        subSym = pSym;
        weight = pWeight;
    }
    string evaluate() const override {
        return subSym->evaluate();
    }
    float getWeight() {
        return weight;
    }
};

class randomSymbol : public symbol {
private:
    vector<weightedSymbol*> symArray;
public:
    randomSymbol(vector<weightedSymbol*> pArr) {
        kind = symbol::random;
        symArray = pArr;
    }
    string evaluate() const override {
        float sum = 0.0;
        for (weightedSymbol* current : symArray) {
            sum += current->getWeight();
        }

        std::random_device rd;
        std::mt19937 gen(rd());
        std::uniform_real_distribution<> dis(0.0, sum);
        float randomResult = dis(gen);

        float prev = 0;
        for (weightedSymbol* current : symArray) {
            if (randomResult < (prev += current->getWeight())) return current->evaluate();
        }
    }
};

我一直在创建这样的符号:

terminalSymbol term_a("a");
terminalSymbol term_b("b");
sequenceSymbol seq_ab({ &term_a, &term_b});

cout << "ab test: " << seq_ab.evaluate() << endl;

但我希望能够像这样或类似的方式来做:

sequenceSymbol seq_ab_2({&terminalSymbol("a"), &terminalSymbol("b")});

cout << "ab test 2: " << seq_ab_2.evaluate() << endl;

这会在 Visual Studio 中产生错误 '&' requires l-value

这是一个非常简单的示例,通常会创建比这更多的变量。在这种情况下,地址被传递给 std::vector<weightedSymbol*>() 构造函数;它与 weightedSymbol() 构造函数相同,它也需要一个指针。这不仅适用于构造函数(如果有另一种方法可以实现相同的功能,它甚至不需要使用构造函数本身),但我想要一种在函数中创建堆对象然后 return 指向它们的指针在这种情况下有效。可能是我需要自己更改 类 才能正常工作,它们应该只提供相同的功能。

最后,我想根据用户输入动态创建这些符号对象。

我已经在线搜索并尝试使用多种不同的东西,但未能获得我想要的功能。实现这个的好方法是什么?大概有一个常用的technique/idiom我可以用,如果有请详细解释给我,我也可以用在其他项目中

您通过指针传递的对象需要以某种方式销毁。在此代码段中,只要您退出块,它们就会自动销毁:

terminalSymbol term_a("a");
terminalSymbol term_b("b");
sequenceSymbol seq_ab({ &term_a, &term_b});

如果创建没有命名变量的对象会怎样?您的 类 永远不会删除您通过指针传递的对象,因此调用者有责任管理每个对象的生命周期。

您的问题的一个解决方案是将对象包装到任何类型的智能指针中。例如:

class sequenceSymbol : public symbol {
public:
    sequenceSymbol(vector<shared_ptr<symbol>> pArr);
};

sequenceSymbol seq_ab_2({
    std::make_shared<terminalSymbol>("a"),
    std::make_shared<terminalSymbol>("b")
});