在同一个 class 的静态函数中创建一个 class 的实例是未定义的行为吗
Is it undefined behavior to create an instance of a class inside a static function of the same class
我的所有搜索在 C++ 解决方案方面收效甚微....
我有一个 class 可以从配置文件中获取信息,我有一个静态函数可以从不同的配置文件中获取站点编号。为了避免重复代码,我在静态函数内部创建了一个 class 实例。编译时没有任何警告(使用 -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());
}
};
这是完全可以接受的代码。我不能给你指出一个说明这不是未定义行为的参考,因为这不是任何人都认为指出的令人担忧的情况。
static
函数就像不在 class 中的普通 friend
函数。如果您在普通的不相关函数中输入类型,那么您将能够创建对象,那么您也应该能够在 static
函数中创建对象。
举个例子,我有 static
个函数,他们在生活中的全部 目的 就是构建我的 class 的成员。我使用这些来确保我的 class 的所有实例都是使用 new
构建的,并通过 shared_ptr
引用。 How do I call ::std::make_shared on a class with only protected or private constructors?
这是完全合法且绝对安全的。
有时将 static
函数视为一个自由函数会有所帮助,它恰好在其声明的 class 范围内。您可以声明类型为 [=11= 的对象] 在自由函数中,所以在 Stanza
.
内的 static
成员函数中这样做很好
在 T
的成员函数中定义类型为 T
的对象在极少数情况下是有风险的,这些情况主要是您必须担心的构造函数或析构函数意外递归。
Unfortunately I can't find any information on whether or not it's undefined behavior. Is it ?
就函数的行为而言,它完全没问题。
我不清楚的是,您是否需要 static
成员函数中 class 的非 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”的内容预计在程序执行过程中会发生变化,您可以保持现有的功能。
我的所有搜索在 C++ 解决方案方面收效甚微....
我有一个 class 可以从配置文件中获取信息,我有一个静态函数可以从不同的配置文件中获取站点编号。为了避免重复代码,我在静态函数内部创建了一个 class 实例。编译时没有任何警告(使用 -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());
}
};
这是完全可以接受的代码。我不能给你指出一个说明这不是未定义行为的参考,因为这不是任何人都认为指出的令人担忧的情况。
static
函数就像不在 class 中的普通 friend
函数。如果您在普通的不相关函数中输入类型,那么您将能够创建对象,那么您也应该能够在 static
函数中创建对象。
举个例子,我有 static
个函数,他们在生活中的全部 目的 就是构建我的 class 的成员。我使用这些来确保我的 class 的所有实例都是使用 new
构建的,并通过 shared_ptr
引用。 How do I call ::std::make_shared on a class with only protected or private constructors?
这是完全合法且绝对安全的。
有时将 static
函数视为一个自由函数会有所帮助,它恰好在其声明的 class 范围内。您可以声明类型为 [=11= 的对象] 在自由函数中,所以在 Stanza
.
static
成员函数中这样做很好
在 T
的成员函数中定义类型为 T
的对象在极少数情况下是有风险的,这些情况主要是您必须担心的构造函数或析构函数意外递归。
Unfortunately I can't find any information on whether or not it's undefined behavior. Is it ?
就函数的行为而言,它完全没问题。
我不清楚的是,您是否需要 static
成员函数中 class 的非 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”的内容预计在程序执行过程中会发生变化,您可以保持现有的功能。