gpt4 book ai didi

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

转载 作者:可可西里 更新时间:2023-11-01 18:35:29 24 4
gpt4 key购买 nike

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

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

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

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

只要 test 中的 f 是静态的,我就希望 createFile 只被调用一次。但是,它被调用了两次。

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

谁能解释一下?非常欢迎除上述之外的解决方案/解决方法。

最佳答案

文字“一”是一个const char [4] .

这段代码:

test("one")

理想情况下想调用test(const char (&)[4])

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

但它不适用于 test(T t)因为您不能按值传递字符串文字。它们通过引用传递。

然而,const char[4]可以衰减到const char* , 可以匹配 template<class T> void func(T t) .

证据就在布丁里:

#include <cstdint>
#include <iostream>
#include <typeinfo>

template <typename T, std::size_t N>
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 <typename T>
void test_mutable(T &t)
{
std::cout << __func__ << " for literal " << t << " T is a " << typeid(T).name() << std::endl;
}

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

template <typename T>
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 <cstdint>
#include <iostream>
#include <typeinfo>
#include <cstdlib>
#include <cxxabi.h>

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

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

template <typename T, std::size_t N>
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 <typename T>
void test_mutable(T &t)
{
std::cout << __func__ << " for literal " << t << " T is a " << demangle(typeid(T).name()) << std::endl;
}

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

template <typename T>
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*

关于模板函数内的 C++ 静态变量初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41595569/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com