1

让我们考虑以下三个文件。

tclass.h:

#include <iostream>
#include <vector>

template<typename rt>
class tclass
{
public:
    void wrapper()
    {
        //Storage is empty
        for(auto it:storage)
        {
        }

        try
        {
            thrower();
        }
        catch(...)
        {
            std::cout << "Catch in wrapper\n";
        }
    }

private:
    void thrower(){}
    std::vector<int> storage;
};

规范.cpp:

#include "tclass.h"

//The exact type does not matter here, we just need to call the specialized method.
template<>
void tclass<long double>::thrower()
{
    //Again, the exception may have any type.
    throw (double)2;
}

主.cpp:

#include "tclass.h"
#include <iostream>

int main()
{
    tclass<long double> foo;
    try
    {
        foo.wrapper();
    }
    catch(...)
    {
        std::cerr << "Catch in main\n";
        return 4;
    }
    return 0;
}

我使用 Linux x64,gcc 4.7.2,文件是用这个命令编译的:

g++ --std=c++11 *.cpp

第一个测试:如果我们运行上面的程序,它会说:

terminate called after throwing an instance of 'double'
Aborted

第二个测试:如果我们for(auto it:storage)tclass.h文件中注释,程序会在main函数中捕获异常。为什么?是否是由于尝试遍历空向量而导致的堆栈损坏?

第三个测试:让我们取消注释该for(auto it:storage)行并将方法专业化从spec.cpp移至main.cpp。然后异常被捕获在wrapper. 这怎么可能,为什么可能的内存损坏不会影响这种情况?

我也尝试用不同的优化级别和 with 来编译它-g,但结果是一样的。

然后我在 Windows 7 x64、VS2012 express 上进行了尝试,使用 x64 版本的 cl.exe 进行编译,没有额外的命令行参数。在第一次测试时,这个程序没有输出,所以我认为它只是默默地崩溃了,所以结果与 Linux 版本相似。对于第二次测试,它再次没有输出,因此结果与 Linux 不同。第三次测试的结果与 Linux 的结果相似。

此代码中是否有任何错误,因此它们可能导致这种行为?第一次测试的结果可能是由编译器中可能的错误引起的吗?

4

1 回答 1

2

使用您的代码,我使用 gcc 4.7.1:

spec.cpp:6: multiple definition of 'tclass<long double>::thrower()'

您可以通过将 .h 中的专业化声明为:

template<> void tclass<long double>::thrower();

于 2013-10-21T13:28:44.443 回答