c++大括号初始化列表,临时生命周期
C++ brace initializer list, temporary lifetime
我有以下代码:
string join(initializer_list<string_view> strings);
initializer_list是std::initializer_list, string_view不是std::string视图,但是非常类似的类,构造函数来自const string&和const char*。
然后我有以下join
的调用:
EXPECT_EQ("this", join({ string("this") }));
经过调查,我发现结果初始化列表的第一个元素不是"this"
,而是" his"
。这是因为string("this")
创建的临时变量的析构函数在string_view
创建之后被调用(因此它包含无效指针)。为什么string("this")
的生命周期没有扩展到完整表达式EXPECT_EQ("this", join({ string("this") }));
的末尾?
好的,正如你所建议的,有一个独立的例子:
#include <iostream>
#include <string>
using namespace std;
class string_view {
public:
string_view(const string& str)
: _begin(str.data())
, _end(str.data() + str.size()) {
std::cout << "string_view(...)" << std::endl;
}
const char* _begin;
const char* _end;
};
void join(initializer_list<string_view> strings) {
std::cout << "join(...)" << std::endl;
for (auto i = 0u; i < 5; ++i) {
std::cout << int(strings.begin()->_begin[i]) << " " << strings.begin()->_begin[i] << std::endl;
}
}
int main() {
join({ string("this") });
return 0;
}
用最新的Visual Studio c++ (Express)编译的程序输出:
string_view(...)
join(...)
0
104 h
105 i
115 s
0
它可能因编译器的不同而不同,因为上面的程序可能是病态的。
我已经研究了调试器中调用的顺序,有一个顺序:
main()
basic_string(const char*)
string_view(const string&)
~basic_string()
initializer_list(...)
join(...)
我希望string("this")
的内容可以在join
函数中使用。但事实并非如此,因为' string("this")之前就被销毁了。
为什么在调用join
函数之前调用临时字符串string("this")
的析构函数,或者换句话说,为什么不将string("this")
的生存期扩展到完整表达式join({ string("this") })
的末尾?
我认为可能在这里发生的是,你正在构造你的initializer_list从一个引用到你的字符串,所以当你的initializer_list已经完成构造字符串超出作用域。
您看到您的字符串不是join()函数的参数,而是您构造的initializer_list的参数。
我的猜测是initializer_list是构造的,您的字符串超出范围,然后您的join()函数试图通过包含在string_view中的引用访问死字符串。
- 如何在共享库的整个生命周期内存储数据
- 如何理解句子的生命周期始于对e的评估
- 它解决了什么问题,对于非真空初始化,生命周期在初始化之前就开始了
- Go/C++gRPC客户端通道和存根生命周期
- 如何将"this"的生命周期移动到C++中的另一个对象中?
- 是否可以通过使用移动/交换 c++11 来延长返回的临时变量的生命周期
- 使用对象的生命周期作为设置器的安全性
- 临时人员的生命周期传递给函数
- 我想知道在构造函数中初始化变量时的生命周期
- Lua 用户数据生命周期管理
- 如何使用 epoll(void* event.data.ptr) 管理 Connection 的生命周期
- C++引用的生命周期
- 在堆栈上有一个对象,而不是在函数的整个生命周期内
- 在 Boost ASIO 服务器中处理生命周期
- C++ lambda 生命周期
- 使用互斥锁跟踪另一个应用的生命周期
- QSharedPointer 或 std::shared_ptr 的生命周期
- 来自async_resolve的 boost::asio::ip::tcp::resolver::iterator 的生命周期是多久?
- 如何调整属于类的唯一指针的字符数组的大小.它必须在程序的整个生命周期中保持活力
- 延长 std::tuple<int&,int> 的生命周期,方法是将其分配给 const std::tuple<int, int>&