Xcode 4.5中"C++标准库"和"C++语言方言"的"编译器默认值"的值是多少?
我的猜测是libstdc ++和GNU ++ 98,但澄清一下会很好.
使用此Xcode版本创建的项目使用标准C++库的新libc ++实现.libc ++库仅在iOS 5.0及更高版本和OS X 10.7及更高版本上可用.12221787
要在项目的早期版本的iOS和OS X上启用部署,请将C++标准库构建设置设置为libstdc ++(Gnu C++标准库).
我注意到创建一个新项目显式设置了GNU ++ 11和libc ++,但"Compiler Default"可能是其他东西.
只是来自的示例代码C++ Primer 5th Edition: 17.3.3. Using the Regular Expression Library
主要文件main.cpp:
#include <iostream>
#include "regexcase.h"
using namespace std;
int main() {
using_regex();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
头文件regexcase.h:
#ifndef REGEXCASE_H_
#define REGEXCASE_H_
#include <regex>
#include <string>
void using_regex();
std::string parseCode(std::regex_constants::error_type etype);
#endif /* REGEXCASE_H_ */
Run Code Online (Sandbox Code Playgroud)
源文件regexcase.cpp:
#include "regexcase.h"
#include <iostream>
using namespace std;
void using_regex() {
// look for words that violate a well-known spelling rule of thumb, "i before e, except after c":
// …Run Code Online (Sandbox Code Playgroud) Peope抱怨这个: 在STL地图中,使用map :: insert比[]更好吗?
访问时
std::map<Key, ExpensiveDefaultConstructorValue> data;
data[key1] // <-- Calls default constructor each time it is called,
// even when the element is there
Run Code Online (Sandbox Code Playgroud)
实现简单而优雅,但效率很低(从unordered_map中获取).
_Tp& operator[](const key_type& __key)
{ return _M_ht.find_or_insert(value_type(__key, _Tp())).second; }
Run Code Online (Sandbox Code Playgroud)
_Tp& operator[](const key_type& __key)
{ return _M_ht.find_or_insert_default(key_type(__key)).second; }
Run Code Online (Sandbox Code Playgroud)
哪里find_or_insert_default会打电话_Tp(),如果只需要(即元素不存在)
是否有一些其他问题可能是由于这种悲观的方法在建立一个新元素之前知道你需要它?
这是标准库,他们应该竭尽全力优化它.为什么不使用这种简单的方法?
我正在将一个应用程序移植到 OS X Darwin,并且出现链接错误,缺少符号,例如:
std::__1::basic_string<char, std::__1::char_traits<char>,
std::__1::allocator<char> >::find_last_of(char const*,
unsigned long,
unsigned long) const
operator delete[](void*)
typeinfo for std::runtime_error
std::set_unexpected(void (*)())
std::exception::~exception()
[...]
Run Code Online (Sandbox Code Playgroud)
我希望这些应该来自 libstdc++,但我不知道如何在使用 clang 时链接它。
这是我尝试的链接行和由此产生的失败:
clang -std=c++11 -stdlib=libc++ -m64 -o ARCH.darwin_1310_i86/release/myExec ARCH.darwin_1310_i86/release/myExec.o ../../src/netcomm/ARCH.darwin_1310_i86/release/libmyExec.a ../../src/common/ARCH.darwin_1310_i86/release/libcommon.a -L../zlib -lz -L../Botan -lbotan-1.10 -lboost_thread-mt
Undefined symbols for architecture x86_64:
"std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::find_last_of(char const*, unsigned long, unsigned long) const", referenced from:
[...]
Run Code Online (Sandbox Code Playgroud)
但这不起作用,我没有找到任何有关如何正确链接它的示例。
我无数次编写了在访问其内存或外部内存后生成分段错误的代码:std::vectorstd::string
std::string test{"hello!"};
std::cout << test[12] << std::endl;
Run Code Online (Sandbox Code Playgroud)
这是一个可以在非优化/调试构建中在运行时捕获的错误,只需简单断言的少量额外成本。(但由于我们正在构建没有-DNDEBUG和没有-O3我们不期望获得最大性能。)
有什么理由std::string::operator[]不这样实施吗?
标准是否禁止在库代码中使用断言?
char std::string::operator[](std::size_t i)
{
// `assert_with_message` only exists in debug mode
#ifndef NDEBUG
assert_with_message(i < this->size(),
"Tried to access character " + std::to_string(i)
+ " from string '" + *this + "' of size "
+ std::to_string(this->size()));
#endif
return data[i];
}
Run Code Online (Sandbox Code Playgroud)
-DNDEBUG在没有编译程序的情况下编译程序并在运行时看到类似此消息的内容将非常有帮助:
断言已触发:尝试从字符串“hello!”访问字符 12 尺寸为 6。
按 (0) 继续。
按 (1) 中止。
请注意,术语“断言”指的是开发/调试构建检查,应从发布/优化构建中完全删除/优化该检查。
initializer_list在使用-stdlib=libstdc++和时编译一个带有空函数的简单Hello文件时,我遇到了一个问题-std=c++11
如果我只使用-std=c++11(这意味着用libc ++编译)
然后文件编译并打印Hello!
如果我评论function_test,我同时使用-std=c++11和-stdlib=libstdc++
然后文件编译并打印Hello!
如果我保留这个功能function_test,我会同时使用-std=c++11和-stdlib=libstdc++
然后我收到以下错误:
$ g++ -stdlib=libstdc++ -std=c++11 -o test test.cpp
test.cpp:1:10: fatal error: 'initializer_list' file not found
#include <initializer_list>
^
1 error generated.
Run Code Online (Sandbox Code Playgroud)
这是我的档案
#include <initializer_list>
#include <iostream>
using namespace std;
void function_test(initializer_list<int> something){}
int main(int argc, char * argv[])
{
cout << "Hello!" << endl;
function_test({0});
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这是我的苹果铿锵版
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr
--with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 7.0.2 …Run Code Online (Sandbox Code Playgroud) 考虑以下用于 GNU 扩展的类型特征的小测试程序 __uint128_t
#include <limits>
#include <type_traits>
using uint128_t = __uint128_t;
int main()
{
static_assert(std::is_unsigned<uint128_t>{}, "");
static_assert(std::is_integral<uint128_t>{}, "");
static_assert(std::numeric_limits<uint128_t>::digits == 128, "");
}
Run Code Online (Sandbox Code Playgroud)
这适用于 g++ 和 libstdc++(工作示例)以及 clang++ 和 libc++(工作示例),但不适用于 clang++ 和 libstdc++ 的组合(失败示例)。
请注意,在所有 3 种情况下,我都使用了-std=gnu++1z标志。
问题:哪种命令行参数组合可以使用 libstdc++ 成功编译我的 clang++ 测试程序?
正如这里 所说std::string的不是模板函数,而是标准选择使用函数重载来为不同类型提供此函数。我的问题是,在这种情况下,当模板/专业化似乎对我更有意义时,为什么要使用重载?考虑一下,如果标准定义了这样的东西:
template <typename T>
std::string std::to_string(const T& v);
Run Code Online (Sandbox Code Playgroud)
然后我们可以在我们的程序中自由地为任何类型添加特化以符合这个签名,因此 C++ 将有一种统一的方式将类型转换为人类可读的字符串。为什么不这样做?当前设计背后的想法是什么?
编辑1:
我对当前设计的主要批评std是不允许向 to 添加重载,因此我们不能编写任何类似的东西,std:to_string(object-that-is-of-user-defined-types)并且必须退回到to_string()在自己的命名空间中定义 a并记住在哪里使用他们的版本或std版本取决于他们正在处理的类型......这对我来说听起来很头疼。
我真正喜欢 Python(或其他一些语言)的一件事是,您可以通过实现一些魔术方法使自己的类型像本机类型一样工作。我认为这个问题的根本是为什么 C++ 决定禁止人们std::to_string()为他们自己的类型实现,从而禁止我们在任何地方都遵循相同的接口。
对于诸如hashor 之类的常见事物to_string(),在语言/stdlib级别上拥有单个界面,然后期望用户遵守该界面,而不是拥有多个界面,不是更好吗?
我在下面的小程序中遇到了以下错误:
#include <vector>
#include <iostream>
using namespace std;
int main() {
vector<int> t;
t.push_back(0);
for(int i = 1; i < 1024; i++) {
auto& x = t[i-1];
t.push_back(x);
t.push_back(x);
t.push_back(x);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
它编译得很好,执行时没有任何错误。但是如果你用 valgrind 运行它(Linux 机器),你会得到一个内存错误:
==122572== Invalid read of size 4
==122572== at 0x10A051: void __gnu_cxx::new_allocator<int>::construct<int, int const&>(int*, int const&) (in /home/casse/tmp/bug)
...
Run Code Online (Sandbox Code Playgroud)
现在,如果您稍微更改上面的代码:
auto x = t[i-1];
Run Code Online (Sandbox Code Playgroud)
(而不是引用,您从向量中复制元素),valgrind 不再抱怨。
任何的想法?
不要问我为什么要做我正在做的事情……那将是一个很长的故事。目前,这篇文章的目的是学习并理解为什么事情没有按照我预期的方式进行。也许我的期望是错误的?
因此,最初我使用最新的编译器(例如gcc 10.2.0 )从源代码构建了自己的 SystemC 2.3.3 库。但是,为了保持与旧版 gcc 的向后兼容性,我请求 C++11 :
./configure CXXFLAGS="-DSC_CPLUSPLUS=201103L"
Run Code Online (Sandbox Code Playgroud)
接下来,我想使用支持 C++11(和相同 ABI)的旧版 gcc 构建一个应用程序,例如gcc 8.2.0:
g++ -std=c++11 sc_main.cpp -I/path/to/systemc/include -L/path/to/systemc/lib -lsystemc -lm -o sim
Run Code Online (Sandbox Code Playgroud)
令我惊讶的是,链接失败:
libsystemc.so: undefined reference to `std::__cxx11::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >::basic_stringstream()
Run Code Online (Sandbox Code Playgroud)
实际上,比较的输出
nm --demangle `/path/to/gcc/10.2.0/bin/g++ --print-file-name libstdc++.so` | grep "std::__cxx11::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >::"
Run Code Online (Sandbox Code Playgroud)
和
nm --demangle `/path/to/gcc/8.2.0/bin/g++ --print-file-name libstdc++.so` | grep "std::__cxx11::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >::"
Run Code Online (Sandbox Code Playgroud)
揭示出一些差异。事实上,前者包含std::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >::basic_stringstream()而后者不包含。
这是预期的吗?这是否意味着一般来说,库的生产者和使用者使用相同的 C++ 版本(和相同的 ABI)是必要的但还不够?还是还有其他我不明白的事情发生?