我想定义一个全局容器(C ++ 03),这里是一个示例代码,我想,这是行不通的。
#include <vector>
#include <string>
using namespace std;
vector<string> Aries;
Aries.push_back("Taurus"); // line 6
int main() {}
编译错误:
prog.cpp:6:1: error: 'Aries' does not name a type
看来我可以定义一个空的全球性载体,但无法填满它。 看起来像在C ++ 03,我也不能指定一个初始值设定,如:
vector<string> Aries = { "Taurus" };
有我在这里犯了一个错误,或者我该如何解决这个问题?
我试图寻找在计算器上,看看是否已经回答过了,但只有在这些帖子就来了: 在C ++全局对象 , 在C ++中定义全局常量 ,这并没有帮助回答这个问题。
当某项功能(如外部声明和初始化main
)没有问题,你不能有功能之外的代码。 你要么需要设置正确的初始化值(如C ++ 11),或填写您的全局对象在主:
std::vector<string> Aries;
/* ... */
int main() {
Aries.push_back("Taurus");
/* ... */
}
其他方式(不填充在主载体)
单值
有哪些不需要其他方式.push_back
在主或其他代码。 例如,如果Aries
应包含仅一个项目时,可以使用std::vector<T>::vector(size_t s, T t)
同s == 1
和t == "Taurus"
:
std::vector<string> Aries(1, "Taurus");
/* ... */
int main() { /* ... */ }
如果您需要在同一价值数时间,你可以简单地调整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));
请注意, 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());
这个例子同时使用拷贝构造函数和范围的构造。 您还可以创建一个临时的载体和使用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;
}
产量
Taurus
Leo
唯一真正的问题,如果你能叫的,是额外的全局变量。
我的经验是,这个“惊人的,但可怕的”(帽尖)解决方案是不可预测的。 你的初始化加载时运行。 你有没有保证,以加载顺序。 因此,使用该集装箱一切都必须在同一个模块无论是在,或以某种方式保证他们进入容器之前的模块被加载。 否则,容器构造还没有运行,但你的代码调用愉快它的存取。
当它出现问题,它会非常错误的,错误是编译器,平台,月亮依赖的阶段 - 在所有情况下不给予最偏远的线索,以什么去了南方。
而就的完整性,该解决方案使用迭代器对构造和朴实的数组初始化。
#include <vector>
#include <string>
#include <iostream>
using namespace std;
string contents[] = {"Taurus", "Leo"};
vector<string> Aries(contents, contents + sizeof contents/sizeof contents[0]);
int main() {
cout << Aries.at(0) << endl;
cout << Aries.at(1) << endl;
}
这可能是更清晰,但它调用更多的拷贝构造函数。