当前位置:  开发笔记 > 编程语言 > 正文

C++静态变量初始化模板函数内部

如何解决《C++静态变量初始化模板函数内部》经验,为你挑选了1个好方法。

我注意到函数模板中静态变量初始化的一个奇怪的行为.请考虑以下示例:

MyFile * createFile()
{
    std::cout << "createFile" << std::endl;
    return nullptr;
}

template 
void test(const T& t)
//void test(T t)
{
    static MyFile *f = createFile();
}

void main()
{
    test("one");
    //test("two");
    test("three");
}

只要ftest是静态的,我预计createFile将只调用一次.但是,它被调用两次.

花了一些时间来解决这个问题,我注意到从参数中删除const引用来test修复它.另一个有趣的事情是传递给函数的字符串的长度也会影响初始化:当参数的长度相等时,静态变量只初始化一次,否则会发生新的初始化.

有人可以解释一下吗?除了上面提到的解决方案/解决方案之外,我们非常欢迎.



1> Richard Hodg..:

文字"一"是一个const char [4].

这段代码:

test("one")

理想情况下会打电话 test(const char (&)[4])

这适用于test(const T&)(因为const char (&) [4]可以绑定const char (const&) [4]).

但它无法工作,test(T t)因为您无法按值传递字符串文字.它们通过引用传递.

但是,const char[4]可以腐烂const char*,可以匹配template void func(T t).

证据在于布丁:

#include 
#include 
#include 

template 
void test_const(const T(&t)[N])
{
    std::cout << __func__ << " for literal " << t << " T is a " << typeid(T).name() << " and N is " << N << std::endl;
}

template 
void test_mutable(T &t)
{
    std::cout << __func__ << " for literal " << t << " T is a " << typeid(T).name() << std::endl;
}

template 
void test_const_ref(const T &t)
{
    std::cout << __func__ << " for literal " << t << " T is a " << typeid(T).name() << std::endl;
}

template 
void test_copy(T t)
{
    std::cout << __func__ << " for literal " << t << " T is a " << typeid(T).name() << std::endl;
}

int main()
{
    test_const("one");
    test_const("three");
    test_mutable("one");
    test_mutable("three");
    test_const_ref("one");
    test_const_ref("three");
    test_copy("one");
    test_copy("three");
}

示例结果(clang):

test_const for literal one T is a c and N is 4
test_const for literal three T is a c and N is 6
test_mutable for literal one T is a A4_c
test_mutable for literal three T is a A6_c
test_const_ref for literal one T is a A4_c
test_const_ref for literal three T is a A6_c
test_copy for literal one T is a PKc
test_copy for literal three T is a PKc

这是一个带有demangled名称的版本(将在clang和gcc上编译):

#include 
#include 
#include 
#include 
#include 

std::string demangle(const char* name)
{
    int status = -1;
    // enable c++11 by passing the flag -std=c++11 to g++
    std::unique_ptr res {
        abi::__cxa_demangle(name, NULL, NULL, &status),
        std::free
    };

    return (status==0) ? res.get() : name ;
}

template 
void test_const(const T(&t)[N])
{
    std::cout << __func__ << " for literal " << t << " T is a " << demangle(typeid(T).name()) << " and N is " << N << std::endl;
}

template 
void test_mutable(T &t)
{
    std::cout << __func__ << " for literal " << t << " T is a " << demangle(typeid(T).name()) << std::endl;
}

template 
void test_const_ref(const T &t)
{
    std::cout << __func__ << " for literal " << t << " T is a " << demangle(typeid(T).name()) << std::endl;
}

template 
void test_copy(T t)
{
    std::cout << __func__ << " for literal " << t << " T is a " << demangle(typeid(T).name()) << std::endl;
}

int main()
{
    test_const("one");
    test_const("three");
    test_mutable("one");
    test_mutable("three");
    test_const_ref("one");
    test_const_ref("three");
    test_copy("one");
    test_copy("three");
}

预期产量:

test_const for literal one T is a char and N is 4
test_const for literal three T is a char and N is 6
test_mutable for literal one T is a char [4]
test_mutable for literal three T is a char [6]
test_const_ref for literal one T is a char [4]
test_const_ref for literal three T is a char [6]
test_copy for literal one T is a char const*
test_copy for literal three T is a char const*

推荐阅读
喜生-Da
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有