Mas*_*Man 4 c++ containers global-variables c++03
我想定义一个全局容器(C++ 03),这是我尝试过的一个示例代码,它不起作用.
#include <vector>
#include <string>
using namespace std;
vector<string> Aries;
Aries.push_back("Taurus"); // line 6
int main() {}
Run Code Online (Sandbox Code Playgroud)
编译错误:
prog.cpp:6:1: error: 'Aries' does not name a type
Run Code Online (Sandbox Code Playgroud)
我似乎可以定义一个空的全局向量,但无法填充它.看起来在C++ 03中,我也无法指定初始化器,例如:
vector<string> Aries = { "Taurus" };
Run Code Online (Sandbox Code Playgroud)
我在这里犯了错误,或者我如何解决这个问题?
我尝试在StackOverflow上搜索,看看之前是否已经回答了这个问题,但是只发现了这些帖子:C++中的全局对象,在C++中定义全局常量,这对此没有帮助.
Zet*_*eta 10
虽然函数之外的声明和初始化(例如main)没有问题,但是您不能在函数之外使用代码.您需要在初始化时设置正确的值(如在C++ 11中),或者在main中填充全局对象:
std::vector<string> Aries;
/* ... */
int main() {
Aries.push_back("Taurus");
/* ... */
}
Run Code Online (Sandbox Code Playgroud)
还有其他不需要的方法.push_back或主要的其他代码.例如,如果Aries只包含一个项目,则可以使用std::vector<T>::vector(size_t s, T t)with s == 1和t == "Taurus":
std::vector<string> Aries(1, "Taurus");
/* ... */
int main() { /* ... */ }
Run Code Online (Sandbox Code Playgroud)
如果你需要几次相同的值,你可以简单地调整s.
现在这有点棘手了.您希望vector使用合适的构造函数填充.std::vector<T>在C++ 03中提供了四种不同的构造函数:
std::vector<T>::vector()std::vector<T>::vector(size_t, T = T())template <class InputIt> std::vector<T>::vector(InputIt, InputIt)std::vector<T>::vector(const vector&)
请注意,所有这些实际上都将分配器作为附加的最后一个参数,但这不是我们关注的问题.我们可以忘记std::vector<T>::vector(),因为我们想要用值填充向量,std::vector<T>::vector(size_t, T)也不适合,因为我们需要不同的值.剩下的是模板化构造函数和复制构造函数.以下示例显示如何使用模板化构造函数:
std::string const values[] = {"Taurus", "Ares", "Testos"};
template <class T, size_t N>
T* begin(T (&array)[N]){ // this is already in C++11, very helpful
return array;
}
template <class T, size_t N>
T* end(T (&array)[N]){
return array+N;
}
std::vector<std::string> Aries(begin(values), end(values));
Run Code Online (Sandbox Code Playgroud)
请注意begin并且end没有必要 - 我们可以简单地使用Aries(values, values+3).但是,事情往往会发生变化,通常会添加一个值或删除一个值.如果您忘记更改偏移量,3您将忘记条目或跨越边界values.
但是,这个解决方案引入了一个新的全局变量,并不是那么好.让我们退后一步.我们需要values使用std::vector<T>::vector(InputIt, InputIt),因为需要有效的范围.并且在我们使用构造函数时必须知道范围,因此它需要是全局的.诅咒!但是看到:我们的工具箱仍然包含一个构造函数,即复制构造函数.为了使用它,我们创建了一个额外的功能:
namespace {
std::vector<std::string> initializer(){
const std::string dummy_array[] = {"Taurus", "Ares", "Testos"};
return std::vector<std::string>(begin(dummy_array), end(dummy_array));
}
}
std::vector<std::string> Aries(initializer());
Run Code Online (Sandbox Code Playgroud)
此示例使用复制构造函数和范围构造函数.您还可以创建一个临时矢量并用于std::vector<T>::push_back在函数中填充它.
我找到了一个简洁的解决方法来"初始化"C++ 03全局STL容器(事实上,以前"全局"执行代码main()).这使用逗号运算符.见例子:
#include <vector>
#include <string>
#include <iostream>
using namespace std;
vector<string> Aries;
// dummy variable initialization to setup the vector.
// using comma operator here to cause code execution in global scope.
int dummy = (Aries.push_back("Taurus"), Aries.push_back("Leo"), 0);
int main() {
cout << Aries.at(0) << endl;
cout << Aries.at(1) << endl;
}
Run Code Online (Sandbox Code Playgroud)
产量
Taurus
Leo
Run Code Online (Sandbox Code Playgroud)
唯一真正的问题,如果你可以称之为,那就是额外的全局变量.
小智 5
我的经验是,这种"惊人但又可怕"(帽子提示)的解决方案是不可预测的.您的初始化在加载时运行.您无法保证加载ORDER.因此,使用该容器的所有内容必须位于同一模块中,或者以某种方式保证模块在访问容器之前已加载.否则,容器构造函数尚未运行,但您的代码很乐意调用其访问器.
当它出错时,它会出错,并且错误是依赖于月亮的编译器,平台和阶段 - 在所有情况下都不会给出最南端的最直接线索.