所以我一直在使用从std :: vector派生的容器.也许这是一个糟糕的设计决定,原因有几个,而且你是否应该做这样的事情的问题在这里有广泛的讨论:
我确信我已经错过了一些讨论......但是在链接中找到了两个观点的合理论据.据我所知,"因为~vector()是非虚拟的"是你不应该从stl容器继承的"规则"的基础.但是,如果我在g ++ 4.9.2中查看std :: vector的实现,我发现std :: vector继承自_Vector_base,而_Vector_base是非虚拟析构函数.
template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
class vector : protected _Vector_base<_Tp, _Alloc>
{
...
~vector() _GLIBCXX_NOEXCEPT
{ std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
_M_get_Tp_allocator()); }
...
}
Run Code Online (Sandbox Code Playgroud)
哪里:
template<typename _Tp, typename _Alloc>
struct _Vector_base
{
...
~_Vector_base() _GLIBCXX_NOEXCEPT
{ _M_deallocate(this->_M_impl._M_start, this->_M_impl._M_end_of_storage
- this->_M_impl._M_start); }
...
}
Run Code Online (Sandbox Code Playgroud)
所以std :: vector的gcc 4.9.2实现继承自带有非虚析构函数的基类.这让我相信这是一种可接受的做法.为什么这样好?这种做法没有危险的具体条件是什么?
I've come across this behavior of std::gcd that I found unexpected:
#include <iostream>
#include <numeric>
int main()
{
int a = -120;
unsigned b = 10;
//both a and b are representable in type C
using C = std::common_type<decltype(a), decltype(b)>::type;
C ca = std::abs(a);
C cb = b;
std::cout << a << ' ' << ca << '\n';
std::cout << b << ' ' << cb << '\n';
//first one should equal second one, but doesn't
std::cout << std::gcd(a, b) …Run Code Online (Sandbox Code Playgroud) C++ Library的GNU实现支持并行模式,这里解释.
__gnu_parallel::sort(v.begin(), v.end());?谢谢你的经验.
萨沙
我有64位的Fedora 20,我的Android开发工具有问题.当我尝试运行项目时,我遇到以下错误:
[2014-05-11 22:08:03 - TestAp] /home/damian/adt-bundle-linux-x86_64-20140321/sdk/build-tools/android-4.4.2/aapt:
error while loading shared libraries: libstdc++.so.6: cannot open
shared object file: No such file or directory
[2014-05-11 22:08:03 - appcompat_v7] /home/damian/adt-bundle-linux-x86_64-20140321/sdk/build-tools/android-4.4.2/aapt:
error while loading shared libraries: libstdc++.so.6: cannot open
shared object file: No such file or directory
Run Code Online (Sandbox Code Playgroud)
我知道我的问题也在这里写,但解决方案不适用于Fedora 20.
考虑以下测试程序:
#include <iostream>
#include <string>
#include <vector>
int main()
{
std::cout << sizeof(std::string("hi")) << " ";
std::string a[10];
std::cout << sizeof(a) << " ";
std::vector<std::string> v(10);
std::cout << sizeof(v) + sizeof(std::string) * v.capacity() << "\n";
}
Run Code Online (Sandbox Code Playgroud)
输出libstdc++和libc++分别是:
8 80 104
24 240 264
Run Code Online (Sandbox Code Playgroud)
如您所见,libc++对于一个简单的程序,需要3倍的内存.实现有何不同会导致这种内存差异?我需要关注,我该如何解决它?
我正在开发一个目前在Linux和uClibc中使用C的嵌入式项目.我们有兴趣将它转移到C++,但我不希望与libstdc ++中的链接相关的开销.我的印象是,如果我们不使用STL中的任何内容,例如iostream或vector,这是可能的.
如何在不链接到libstdc ++的情况下直接编译g ++?
首先,请考虑以下代码:
#include <iostream>
#include <functional>
struct Noisy
{
Noisy() { std::cout << "Noisy()" << std::endl; }
Noisy(const Noisy&) { std::cout << "Noisy(const Noisy&)" << std::endl; }
Noisy(Noisy&&) { std::cout << "Noisy(Noisy&&)" << std::endl; }
~Noisy() { std::cout << "~Noisy()" << std::endl; }
};
void foo(Noisy n)
{
std::cout << "foo(Noisy)" << std::endl;
}
int main()
{
Noisy n;
std::function<void(Noisy)> f = foo;
f(n);
}
Run Code Online (Sandbox Code Playgroud)
以及它在不同编译器中的输出:
Noisy()
Noisy(const Noisy&)
Noisy(Noisy&&)
foo(Noisy)
~Noisy()
~Noisy()
~Noisy()
Run Code Online (Sandbox Code Playgroud)
Noisy() …Run Code Online (Sandbox Code Playgroud) 我担心在内核土地,我将无法访问之类的东西std::move,std::forward,std::initializer_list,等.虽然这些功能是内置到语言,他们仍然需要相应的头文件和库实现.以下是否足以利用移动语义,或者我是否需要完整的9码并移植C++库?
template <typename T>
typename remove_reference<T>::type&& move(T&& arg)
{
return static_cast<typename remove_reference<T>::type&&>(arg);
}
Run Code Online (Sandbox Code Playgroud) 考虑这种简化且非常具体的递归变体实现std::variant:
#include <map>
#include <variant>
struct recursive_tag;
template <typename...>
struct RecursiveVariant;
template <>
struct RecursiveVariant<int, std::map<int, recursive_tag>>
: std::variant<int, std::map<int, RecursiveVariant<int, std::map<int, recursive_tag>>>>
{
using underlying = std::variant<int,
std::map<int, RecursiveVariant<int, std::map<int, recursive_tag>>>>;
using underlying::underlying;
};
int main() {
RecursiveVariant<int, std::map<int, recursive_tag>> rv;
}
Run Code Online (Sandbox Code Playgroud)
由于尝试实例化std::pair<const int, recursive_tag>而无法在gcc 7/8上编译,因为它recursive_tag是一个不完整的类型,它本身也会失败.
但是,编译器错误call-stack中没有任何内容向我指出为什么 std::pair<const int, recursive_tag>需要实例化.最重要的是:
变体:252:48:'
void std::__detail::__variant::__erased_dtor(_Variant&&) [with _Variant = const std::__detail::__variant::_Variant_storage<false, int, std::map<int, RecursiveVariant<int, std::map<int, recursive_tag, std::less<int>, std::allocator<std::pair<const int, recursive_tag> > > >, std::less<int>, …
考虑以下结构,std::optional其中包含一个绝对具有“正常”默认构造函数的类型。
#include <optional>
#include <string>
struct Foo
{
Foo() = default;
const std::optional<std::string> m_value;
};
bool function()
{
Foo foo;
return bool(foo.m_value);
}
Run Code Online (Sandbox Code Playgroud)
使用 clang 9 编译以下内容(使用系统的默认值libstdc++,对于它的 gcc 8)会给出一个意外警告:
<source>:6:5: warning: explicitly defaulted default constructor is implicitly deleted [-Wdefaulted-function-deleted]
Foo() = default;
^
<source>:7:38: note: default constructor of 'Foo' is implicitly deleted because field 'm_value' of const-qualified type 'const std::optional<std::string>' (aka 'const optional<basic_string<char> >') would not be initialized
const std::optional<std::string> m_value;
^
Run Code Online (Sandbox Code Playgroud)
Foo foo;由于它使用了所述已删除的构造函数,因此也存在硬错误。