在同一个类的静态函数内创建类的实例是不确定的行为

时间:2017-10-03 21:31:07

标签: c++ c++03

我所有的搜索在C ++解决方案方面都收效甚少 我有一个从配置文件中获取信息的类,我有一个静态函数,可以从不同的配置文件中获取站点号。为了避免重复代码,我在静态函数内部创建了一个类的实例。这编译时没有任何警告(使用-Wall)。

不幸的是,我找不到任何关于它是否是未定义行为的信息。是吗?

#include <iostream>
#include <fstream>
#include "srxDSLog.H"

extern  SrxDsLog *Logger;

class Stanza {
private:
    std::string config_file_path_;

public:
    Stanza(std::string config_file_path) { 
        config_file_path_ = config_file_path;
    }

    std::string GetValue(std::string config_section, std::string config_setting) {
        std::ifstream config_file(config_file_path_.c_str(), std::ios::in);
        std::string current_section, line;
        for ( ; std::getline(config_file, line); ) {
            line = rtrim(line);
            if (line.find(" ") == std::string::npos && line.find(":") != std::string::npos) {
                current_section = line.substr(0, line.find(":"));
                continue;
            }
            if (current_section == config_section) {
                if (line.find(config_setting) != std::string::npos && line.find("=") != std::string::npos) {
                    return line.substr(line.find(config_setting) + config_setting.length() + 3); // we're getting the string starting after the name of the setting + " = " + 1. We're assuming there's exactly 1 space 
                }
            }
        }
        if (current_section.empty()) {
            Logger->WriteLog("Couldn't find section: " + config_section, LOG_ERROR, "Stanza::GetValue");
            return "";
        }
        else {
            Logger->WriteLog("Couldn't find setting: " + config_setting, LOG_ERROR, "Stanza::GetValue");
            return "";
        }
        Logger->WriteLog("Somehow reached the end of function without returning", LOG_ERROR, "Stanza::GetValue");
        return "";
    }

    static std::string rtrim(std::string input) {
        if (input.find_last_not_of(" ") == input.length() - 1) {
            return input;
        }
        else {
            return input.substr(0, input.find_last_not_of(" ") + 1);
        }
    }

    static int GetStoreNumber() {
        Stanza store_config("/u/data/store.cfg");
        std::string store_number =  store_config.GetValue("store", "site");
        return atoi(store_number.c_str());
    }

};

3 个答案:

答案 0 :(得分:4)

这是完全合法且完全安全的。

static函数视为一个自由函数有时会有所帮助,它恰好在它声明的类的范围内。你可以声明Stanza类型的对象一个自由函数,所以在static内的Stanza成员函数中这样做很好。

T的成员函数中定义类型为T的对象的风险很少,而且这些情况主要是构造函数或析构函数,您需要担心意外递归。

答案 1 :(得分:1)

这是完全可以接受的代码。我不能指出你的参考文献说它不是未定义的行为,因为它不是任何人都想过指出令人担忧的情况。

static函数就像一个不在类中的普通friend函数。如果您能够在普通无关函数中创建对象,那么您也应该能够在static函数内部。

作为一个例子,我有static个函数,他们在生活中的整个目的就是构建我的班级成员。我使用它们来确保我的类的所有实例都是使用new构造的,并通过shared_ptr引用。 How do I call ::std::make_shared on a class with only protected or private constructors?

答案 2 :(得分:1)

  

不幸的是,我找不到任何关于它是否是未定义行为的信息。是吗?

在功能的行为方面完全没问题。

我不清楚您是否需要static成员函数中的非static类实例。

如果在执行程序期间不希望更改文件“/u/data/store.cfg”的内容,则可以使用static变量。

static int GetStoreNumber() {
    static Stanza store_config("/u/data/store.cfg");
    std::string store_number =  store_config.GetValue("store", "site");
    return atoi(store_number.c_str());
}

您可以进一步优化使用:

static int GetStoreNumber() {
    static int number = getStoreNumber("/u/data/store.cfg");
    return number;
}

static int GetStoreNumber(std::strinc const& filename) {
    Stanza store_config(filename);
    std::string store_number =  store_config.GetValue("store", "site");
    return atoi(store_number.c_str());
}

如果预期文件“/u/data/store.cfg”的内容在程序执行期间发生变化,您可以保留该功能。