如何正确初始化结构体及用结构体初始化std::unique_ptr?
问题描述
以下代码编译报错:
int main() { struct test { std::string s; }; std::unique_ptr<struct test> p = nullptr; p = std::make_unique<struct test>("test"); printf("%s\n", p->s); }
编译错误信息:
In file included from /usr/include/c++/14/memory:78, from struct-pointer.cc:2: /usr/include/c++/14/bits/unique_ptr.h: In instantiation of ‘std::__detail::__unique_ptr_t<_Tp> std::make_unique(_Args&& ...) [with _Tp = main()::test; _Args = {const char (&)[5]}; __detail::__unique_ptr_t<_Tp> = __detail::__unique_ptr_t<main()::test>]’: struct-pointer.cc:13:38: required from here 13 | p = std::make_unique<struct test>("test"); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~ /usr/include/c++/14/bits/unique_ptr.h:1076:30: error: no matching function for call to ‘main()::test::test(const char [5])’ 1076 | { return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); } | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ struct-pointer.cc:6:12: note: candidate: ‘main()::test::test()’ 6 | struct test | ^~~~ struct-pointer.cc:6:12: note: candidate expects 0 arguments, 1 provided struct-pointer.cc:6:12: note: candidate: ‘main()::test::test(const main()::test&)’ struct-pointer.cc:6:12: note: no known conversion for argument 1 from ‘const char [5]’ to ‘const main()::test&’ struct-pointer.cc:6:12: note: candidate: ‘main()::test::test(main()::test&&)’ struct-pointer.cc:6:12: note: no known conversion for argument 1 from ‘const char [5]’ to ‘main()::test&&’
尝试无构造函数的结构体初始化:
struct test foo = { "test" };
这段代码能编译,但执行printf("%s\n", foo.s);时输出垃圾值而非"test"。
提出两个问题:
- 如何正确初始化结构体,使printf语句输出"test"?
- 使用
std::unique_ptr而非局部变量时,如何初始化struct test?
解答
问题1:正确初始化结构体并输出"test"
垃圾值问题和结构体初始化无关,是printf使用错误导致的。printf的%s格式符需要接收C风格字符串(const char*),但你直接传递了std::string对象,这会让printf读取错误的内存地址,输出垃圾内容。
正确的处理方式有两种:
- 用C++原生的
std::cout输出,它支持直接打印std::string:
#include <iostream> #include <string> int main() { struct test { std::string s; }; struct test foo = { "test" }; // 聚合初始化本身是正确的 std::cout << foo.s << std::endl; }
- 一定要用
printf的话,调用std::string的c_str()方法获取C风格字符串指针:
#include <cstdio> #include <string> int main() { struct test { std::string s; }; struct test foo = { "test" }; printf("%s\n", foo.s.c_str()); }
问题2:用std::unique_ptr初始化struct test
编译错误是因为std::make_unique会尝试调用test的构造函数,但你的结构体没有能接收const char*的构造函数,只有默认、拷贝、移动构造函数。
解决方法有两种:
方法一:给结构体加自定义构造函数
添加一个接收const char*的构造函数,让std::make_unique可以正确调用:
#include <cstdio> #include <memory> #include <string> int main() { struct test { std::string s; test(const char* str) : s(str) {} }; std::unique_ptr<struct test> p = std::make_unique<struct test>("test"); printf("%s\n", p->s.c_str()); }
方法二:用new配合聚合初始化
不想加构造函数的话,直接用new结合列表初始化创建对象,再交给unique_ptr管理:
#include <cstdio> #include <memory> #include <string> int main() { struct test { std::string s; }; std::unique_ptr<struct test> p = std::unique_ptr<struct test>(new struct test{ "test" }); // 更简洁的写法:auto p = std::unique_ptr<struct test>(new struct test{ "test" }); printf("%s\n", p->s.c_str()); }
这种方式利用聚合类型的列表初始化特性,不需要自定义构造函数就能完成初始化。
内容的提问来源于stack exchange,提问作者user1785730
相关产品推荐
相关产品推荐

