为什么 printf 不能直接输出 string?一次搞懂 C++ 中最常见的类型报错
作者:野牛程序员:2026-05-18 14:00:27C++阅读 1996
为什么 printf 不能直接输出 string?一次搞懂 C++ 中最常见的类型报错
很多刚开始学 C++ 的同学,都会遇到这样一个报错:
[Error] cannot pass objects of non-trivially-copyable type
'std::string {aka class std::basic_string<char>}' through '...'
第一次看到这串英文时,脑子基本是懵的。
什么叫:
non-trivially-copyable
什么又叫:
through '...'
其实问题并不复杂,本质上只有一句话:
printf 不能直接输出 string 类型。
来看一个真实案例。
代码如下:
#include<iostream>
#include<string>
#include<cstdio>
using namespace std;
int main(){
string t1,t2;
int b = 5;
t1 = "km";
t2 = "m";
printf("%d %s = %d %s\n",
b,
t1.c_str(),
b * 1000,
t2.c_str());
return 0;
}很多人会觉得:
t1 不就是字符串吗?
为什么不能输出?
问题就出在:
printf
其实是 C 语言时代留下来的函数。
而:
string
是 C++ 的类对象。
两者并不是一个体系。
先理解 %s 到底需要什么。
在 printf 里:
%s
要求后面的参数必须是:
char *
也就是:
字符数组地址。
比如:
char s[] = "hello";
printf("%s", s);
这是合法的。
因为:
s
本质就是字符地址。
但:
string t1 = "hello";
这里的 t1 已经不是字符数组了。
它是:
std::string
对象。
对象内部可能有:
长度
容量
内存管理
动态分配
各种成员函数
所以:
printf
根本看不懂。
这就像:
拿老式插头去插新式接口。
类型不兼容。
于是编译器直接报错。
正确做法是什么?
需要把 string 转成 C 风格字符串。
也就是:
c_str()
修改后:
printf("%d %s = %d %s",
b,
t1.c_str(),
b * 1000,
t2.c_str());
这样就正常了。
因为:
t1.c_str()
返回的是:
const char *
这才符合 %s 的要求。
完整代码:
#include<iostream>
#include<string>
#include<cstdio>
using namespace std;
int main(){
string t1,t2;
int b = 5;
t1 = "km";
t2 = "m";
printf("%d %s = %d %s\n",
b,
t1.c_str(),
b * 1000,
t2.c_str());
return 0;
}输出:
5 km = 5000 m
很多初学者会问:
既然这么麻烦,为什么还要用 printf?
实际上。
现在的 C++ 开发里:
已经越来越少使用 printf 了。
因为:
cout
本身就支持 string。
直接写:
cout << b << " "
<< t1 << " = "
<< b * 1000 << " "
<< t2 << endl;
更加自然。
也更安全。
不会出现类型不匹配的问题。
再深入一点。
为什么报错里会出现:
through '...'
这里的:
...
指的是:
可变参数。
比如:
printf("%d %d",a,b);后面的参数数量是不固定的。
这种函数本身无法自动检查对象类型。
所以:
C++ 对复杂对象会非常谨慎。
像:
string
vector
map
这些对象。
都不能直接往 printf 里乱塞。
否则很容易出问题。
所以以后看到类似错误时,可以快速想到:
是不是把 C++ 对象直接传给了 printf。
这是新手阶段特别常见的问题。
基本每个学 C++ 的人都会踩一次。
野牛程序员教少儿编程与信息学奥赛-微信|电话:15892516892

- 上一篇:从单位换算题,聊聊 C++ 里的两种写法:map 与 非 map
- 下一篇:
