#include "stdafx.h"
#include "iostream"
#include "string"
using namespace std;
void main()
{
string a = "a";
string b(1, -70); /*constructor, create a string having 1 character that its value is equal to -70*/
cout << (b > a ? b : a);
}
//output on screen: b was printed, not a (!)
Run Code Online (Sandbox Code Playgroud)
虽然b的值小于a的值,为什么b>a?我该如何纠正这种情况?
在C++03中,对于std::string类c_str()和data()方法有不同的行为。
第一个返回一个以空结尾的字符数组,最后一个的管理完全依赖于实现。事实上,c_str() 可以返回指向另一个预分配缓冲区的指针,该缓冲区始终包含一个以 null 结尾的字符串,但这不是强制性的。然而,复杂性必须是恒定的。
第二个只是返回指向 的内部缓冲区的指针std::string,该缓冲区可以是空终止的,也可以不是。
因此,在 C++03 中,您可能会猜测强制转换运算符 toconst char*不是一个好主意。事实上,大多数时候,预期的行为是有一个以 null 结尾的 C 风格字符串,但是,由于 的实现c_str()可能会有所不同,因此强制转换运算符后面可能存在隐藏的开销。在另一种情况下,如果强制转换运算符返回与 相同的结果,可能会带来混乱data()。
但是,对于 C++11,c_str()和data()具有相同的行为。c_str()返回指向对象内部缓冲区的指针std::string。强制转换运算符 toconst char*不再含糊不清。std::string为什么C++11 中的类中没有此方法?
谢谢 !
当我暂停程序时,我和我的团队遇到了 Visual Studio 显示乱码而不是正确字符串内容的问题。里面的字符串数据是正确的,只是VS的调试器不知何故丢失了。
\n\n我将正确的内容标记为绿色,错误的内容标记为红色。
\n\n\n\n你可以看到std::string定义为
const std::string testStdString = "contents of std::string";\nRun Code Online (Sandbox Code Playgroud)\n\n显示为"\\b\xc3\x84\xc4\x8eD\\x19"调试悬停和监视窗口。但 C 弦.c_str()显示良好。写入的控制台cout也显示正常。\n这个损坏的值在每次运行时都会发生变化。
在原始视图模式下,您可以看到指针内容显示为 ASCII 时,看起来就像调试器认为的字符串内容。那么也许有一些短字符串优化相关的问题?
\n\n\n\n如果将其解码为字符串:
\n\n"\\b\xc3\x84\xc4\x8eD\\x19"\n [0x00000000]: 0x08 \'\\b\'\n [0x00000001]: 0xc4 \'\xc3\x84\'\n [0x00000002]: 0xcf \'\xc4\x8e\'\n [0x00000003]: 0x44 \'D\'\n [0x00000004]: 0x19 \'\\x19\'\n [0x00000005]: 0x00 \'\\0\'\nRun Code Online (Sandbox Code Playgroud)\n\n它buf与原始视图中可见的属性匹配:(0x0000001944cfc408相反顺序)。
问题仅影响std::string和std::wstringC 字符串工作正常。当我尝试使用std::string::c_str()它时效果也很好。
当我尝试使用一个简单的新项目时,不会出现此问题 - 但在我们使用本机 C++ 和 C# UWP 解决方案的 …
我最近了解到成员函数可以是ref-qualified,这使我可以编写
struct S {
S& operator=(S const&) & // can only be used if the implicit object is an lvalue
{
return *this;
}
};
S operator+(S const &, S const &) {
return {};
}
Run Code Online (Sandbox Code Playgroud)
从而阻止用户做类似的事情
S s{};
s + s = S{}; // error
Run Code Online (Sandbox Code Playgroud)
然而,我看到该std::string成员operator= 并没有这样做。所以下面的代码编译时没有警告
std::string s;
s + s = s;
Run Code Online (Sandbox Code Playgroud)
有理由允许这样做吗?
如果没有,将来是否可以添加引用限定符,或者会以某种方式破坏现有代码吗?
我试图找到两个字符串的最大值,它在第一种情况下(传递std::string变量时)给出了正确的答案,但在第二种情况下(传递直接字符串时)给出了错误。
#include<bits/stdc++.h>
using namespace std;
int main()
{
// Case 1
string str1 = "abc", str2 = "abcd";
cout << max(str1, str2) << endl;
// Case 2
cout << max("abc", "abcd") << endl;
}
Run Code Online (Sandbox Code Playgroud) 我应该如何编写一个高效的异常类来显示可以通过在运行时修复源代码错误来防止的错误?
这就是我选择的原因std::invalid_argument。
我的异常类(显然不起作用):
class Foo_Exception : public std::invalid_argument
{
private:
std::string Exception_Msg;
public:
explicit Foo_Exception( const std::string& what_arg );
virtual const char* what( ) const throw( );
};
explicit Foo_Exception::Foo_Exception( const std::string& what_arg ) // how should I write this function???
{
Exception_Msg.reserve( 130000 );
Exception_Msg = "A string literal to be appended, ";
Exception_Msg += std::to_string( /* a constexpr int */ );
Exception_Msg += /* a char from a const unordered_set<char> */;
}
const char* Foo_Exception::what( ) …Run Code Online (Sandbox Code Playgroud) 我正在使用 C 例程写入 std::string 的数据字段。这是一个人为的示例,实际上我通过网络获取一个非空终止的字符串及其大小:
#include <string>
#include <cstdio>
#include <cstring>
const char* str = "Some examplory string..";
int main()
{
std::string some_str;
some_str.resize(strlen(str));
std::strcpy(&some_str.front(), str);
printf(some_str.c_str());
}
Run Code Online (Sandbox Code Playgroud)
现在根据cppref 的说法,不存在resize()仅调整大小且不使用 '\0' 或其他内容初始化内存的重载。但如果我所做的只是再次覆盖它,为什么我要为此付费呢?这可以通过某种方式避免吗?
我想知道如何正确处理函数中的字符串输入,如果我知道我将必须在其中创建一个副本以将其放入容器中。
我想这样做:
void foo(const string& s){
container.push(s);
}
Run Code Online (Sandbox Code Playgroud)
但是如果我传递一个 char* 字符串,我将制作 2 个副本,首先是在调用 foo 时,然后是在将其传递到容器时。
我的第二个想法是使用 string_view,正如人们常说的,如果你可以使用视图,你就应该使用。所以我的函数的第二个版本如下所示:
void foo2(string_view s){
container.push(string(s));
}
Run Code Online (Sandbox Code Playgroud)
好的,现在无论给我什么类型的字符串,我都会只制作一个副本。但后来我开始思考,为什么我不能接受一个字符串作为函数的参数,像这样简化它:
void foo3(string s){
container.push(std::move(s));
}
Run Code Online (Sandbox Code Playgroud)
但现在我必须确保我的容器正确利用移动语义,这样它最终不会制作另一个副本!由于此容器对象是模板化类型,因此意味着使用完美转发等,这本身就是大量工作。
目前我不知道该选择哪个选项,所以想请教您一些建议。我还觉得我想得太多了,因为这最终可能不会对性能产生太大影响,但我想做得正确。提前致谢。
如果我捕获异常,我想将错误消息(该方法以 C 样式字符串形式返回)转换what()为std::u8string(UTF-8 字符串)。例如:std::u8string(error.what());
如何将 a 转换char*为 a std::u8string?
我有一个char已知大小的缓冲区(为简单起见,假设是一个固定大小的数组),我想从中构造一个std::string. 此缓冲区中的字符串可能以 null 结尾,或者可能会一直运行到并包括最后一个char. 我希望创建一个std::string包含直到第一个空字节或缓冲区末尾的内容(以先到者为准)的内容。
这似乎是一件很常见的事情,但在查看 API 时,解决方案对我来说并不是显而易见的std::string。
std::string有一个构造函数接受范围const char *和长度,但是这个构造函数很高兴地继续过去的空字节并将它们复制到字符串中。std::strlen()缓冲区string不是一个选项,因为strlen要求缓冲区以空终止,但情况可能并非如此。std::string包含空值的对象,然后将其大小调整到第一个空值之前,但这会浪费内存,因为string会被过度分配。执行此操作的最佳和/或惯用方法是什么?