如果我有一个类定义的类
class A {
protected:
~A(){ }
};
Run Code Online (Sandbox Code Playgroud)
然后我可以动态分配个人以及像这样的对象数组
A* ptr1 = new A;
A* ptr2 = new A[10];
Run Code Online (Sandbox Code Playgroud)
但是,当我为这个类定义构造函数时
class A {
public:
A(){}
protected:
~A(){ }
};
Run Code Online (Sandbox Code Playgroud)
然后我可以创建单个对象
A* ptr = new A;
Run Code Online (Sandbox Code Playgroud)
但是当我尝试动态分配对象数组时
A* ptr = new A[10];
Run Code Online (Sandbox Code Playgroud)
编译器(gcc-5.1和Visual Studio 2015)开始抱怨A :: ~A()是不可访问的.
谁能解释一下: -
1-为什么定义和未定义构造函数的行为差异.
2-定义构造函数时,为什么允许创建单个对象而不是对象数组.
为了使我的代码标准化并使其更具可移植性,我更换了
#ifdef __GNUC__
typedef __attribute__((aligned(16))) float aligned_block[4];
#else
typedef __declspec(align(16)) float aligned_block[4];
#endif
Run Code Online (Sandbox Code Playgroud)
同
typedef float alignas(16) aligned_block[4];
Run Code Online (Sandbox Code Playgroud)
在C++ 11中.然而,gnu(4.8)并不喜欢这样但是抱怨
test.cc:3:9: warning: attribute ignored [-Wattributes]
typedef float alignas(16) aligned_block[4];
^
test.cc:3:9: note: an attribute that appertains to a type-specifier is ignored
Run Code Online (Sandbox Code Playgroud)
而clang 3.2没有发出警告(即使有-Weverything -Wno-c++98-compat -pedantic).所以我想知道我上面的代码是否正确,更一般地说,我alignas()可以在哪里放置.
编辑(2013年4月):
该标准的相关文章是7.6.2,特别是7.6.2.1
对齐说明符可以应用于变量或类数据成员,但不应该应用于位字段,函数参数,catch子句的形式参数(15.3)或使用注册存储类说明符.对齐说明符也可以应用于类或枚举类型的声明.带省略号的对齐说明符是包扩展(14.5.3).
正如Red XIII已经挖出来的那样.但是,我不够专业,不知道这对我上面的测试意味着什么.
如果clang接受我的属性这一事实意味着什么,那么也许值得一提的是,当试图使用using指令代替a时typedef,clang也会抱怨.此外,与此问题的早期版本中的陈述相反,gcc不仅警告,而且实际上忽略了我对齐的愿望.
我知道2的幂可以使用<<运算符来实现.10的力量怎么样?喜欢10 ^ 5?在C++中有没有比pow(10,5)更快的方法?这是一个非常直接的计算手工.但由于数字的二进制表示,计算机似乎并不容易......让我们假设我只对整数幂,10 ^ n感兴趣,其中n是整数.
我需要计算一大组数字的几何平均值,其值不是先验有限的.天真的方式是
double geometric_mean(std::vector<double> const&data) // failure
{
auto product = 1.0;
for(auto x:data) product *= x;
return std::pow(product,1.0/data.size());
}
Run Code Online (Sandbox Code Playgroud)
但是,由于累积的下溢或溢出,这可能会失败product(注意:long double并不能真正避免这个问题).那么,下一个选择是总结对数:
double geometric_mean(std::vector<double> const&data)
{
auto sumlog = 0.0;
for(auto x:data) sum_log += std::log(x);
return std::exp(sum_log/data.size());
}
Run Code Online (Sandbox Code Playgroud)
这可行,但需要调用std::log()每个元素,这可能很慢.我可以避免吗?例如,通过跟踪(相当于)指数和product单独累计的尾数?
(是的,我知道有一个问题几乎相同的标题,但得到的答复是不能令人满意的,见下文)
编辑抱歉,原始问题没有使用编译器优化.现在已经修复了这个问题,但是为了避免琐碎的优化并且更接近我的实际用例,测试已经分成两个编译单元.
std::vector<>具有线性复杂性的构造函数在性能关键应用程序方面是一个令人讨厌的事实.考虑这个简单的代码
// compilation unit 1:
void set_v0(type*x, size_t n)
{
for(size_t i=0; i<n; ++i)
x[i] = simple_function(i);
}
// compilation unit 2:
std::vector<type> x(n); // default initialisation is wasteful
set_v0(x.data(),n); // over-writes initial values
Run Code Online (Sandbox Code Playgroud)
当构建时浪费了大量时间x.正如这个问题所探讨的那样,传统的方法似乎只是保留存储和使用push_back()来填充数据:
// compilation unit 1:
void set_v1(std::vector<type>&x, size_t n)
{
x.reserve(n);
for(size_t i=0; i<n; ++i)
x.push_back(simple_function(i));
}
// compilation unit 2:
std::vector<type> x(); x.reserve(n); // no initialisation
set_v1(x,n); // using push_back()
Run Code Online (Sandbox Code Playgroud)
然而,正如我的评论所指出的那样,push_back()本质上是缓慢的,这使得第二种方法实际上比第一种方法慢 …
在模板元编程中,可以在返回类型上使用SFINAE 来选择某个模板成员函数,即
template<int N> struct A {
int sum() const noexcept
{ return _sum<N-1>(); }
private:
int _data[N];
template<int I> typename std::enable_if< I,int>::type _sum() const noexcept
{ return _sum<I-1>() + _data[I]; }
template<int I> typename std::enable_if<!I,int>::type _sum() const noexcept
{ return _data[I]; }
};
Run Code Online (Sandbox Code Playgroud)
但是,这对构造函数不起作用.假设,我想声明构造函数
template<int N> struct A {
/* ... */
template<int otherN>
explicit(A<otherN> const&); // only sensible if otherN >= N
};
Run Code Online (Sandbox Code Playgroud)
但不允许这样做otherN < N.
那么,SFINAE可以在这里使用吗?我只对允许自动模板参数扣除的解决方案感兴趣
A<4> a4{};
A<5> a5{};
A<6> …Run Code Online (Sandbox Code Playgroud) 我有一个很大但可能变化的对象,它们被同时写入.我想用互斥锁保护访问权限.为此,我认为我使用了一个std::vector<std::mutex>,但这不起作用,因为std::mutex没有复制或移动构造函数,同时std::vector::resize()需要.
这个难题的推荐解决方案是什么?
编辑:所有C++随机访问容器是否需要复制或移动构造函数来重新调整大小?std :: deque会帮助吗?
再次编辑
首先,感谢您的所有想法.我对避免突变和/或将它们移动到对象中的解决方案不感兴趣(我不提供细节/原因).因此,考虑到我想要一个可调数量的mutices(在没有锁定互斥锁时保证调整的情况)的问题,那么似乎有几种解决方案.
1我可以使用固定数量的mutices并使用哈希函数从对象映射到mutices(如Oblivous上尉的答案).这将导致冲突,但如果mutices的数量远大于线程数,但仍然小于对象数,则冲突的数量应该很小.
2我可以定义一个包装类(如在ComicSansMS的答案中),例如
struct mutex_wrapper : std::mutex
{
mutex_wrapper() = default;
mutex_wrapper(mutex_wrapper const&) noexcept : std::mutex() {}
bool operator==(mutex_wrapper const&other) noexcept { return this==&other; }
};
Run Code Online (Sandbox Code Playgroud)
并使用一个std::vector<mutex_wrapper>.
3我可以std::unique_ptr<std::mutex>用来管理单个互斥体(如Matthias的答案).这种方法的问题是每个互斥锁在堆上单独分配和解除分配.因此,我更喜欢
4 std::unique_ptr<std::mutex[]> mutices( new std::mutex[n_mutex] );
当n_mutex最初分配一定数量的mutices时.如果以后发现这个数字不够,我只是
if(need_mutex > n_mutex) {
mutices.reset( new std::mutex[need_mutex] );
n_mutex = need_mutex;
}
Run Code Online (Sandbox Code Playgroud)
那么我应该使用这些(1,2,4)中的哪一个?
我一直在使用(并且看到用过)static_assert来标记模板参数值的不需要的值.然而,对于我遇到的所有情况,通过SFINAE禁用那些不需要的值似乎更好,更优雅.例如
template<typename T,
class = std::enable_if<std::is_floating_point<T>::value>::type>
struct Foo { ... };
Run Code Online (Sandbox Code Playgroud)
代替
template<typename T>
struct Foo {
static_assert(std::is_floating_point<T>::value,
"Foo<T>: T must be floating point :-(");
...
};
Run Code Online (Sandbox Code Playgroud)
所以我的问题是:何时使用static_assert而不是SFINAE?为什么?
编辑
我认为到目前为止我所学到的是以下内容
1 SFINAE是一个多功能且功能强大但可能非常复杂的工具,可用于许多任务,包括功能过载解决(有些人认为这是其唯一目的).
2 SFINAE可以以一种相对简单的方式使用static_assert,除非它出现在(类或函数的)声明中而不是它的定义(或者是否可以插入static_assert一个类,例如,类前向声明?) .这使得更加逐字,更清晰的代码.然而,因为SFINAE很复杂,所以它往往比简单的更难static_assert.
3另一方面,static_assert有一个更清晰的编译器错误消息的好处,有些人似乎认为这两者的主要目的.
Clang警告(当使用-Weverything或时Wglobal-constructors)关于静态对象的构造函数.
warning: declaration requires a global constructor
[-Wglobal-constructors]
A A::my_A; // triggers said warning
^~~~
Run Code Online (Sandbox Code Playgroud)
为什么这是相关的,应该如何处理这个警告?
简单示例代码:
class A {
// ...
static A my_A;
A();
};
A A::my_A; // triggers said warning
Run Code Online (Sandbox Code Playgroud)