具体来说,如果我有一系列if... else if语句,并且我事先知道每个语句将评估的相对概率,true它按照概率的顺序对它们进行排序有多大差异?例如,我应该更喜欢这个:
if (highly_likely)
//do something
else if (somewhat_likely)
//do something
else if (unlikely)
//do something
Run Code Online (Sandbox Code Playgroud)
对此?:
if (unlikely)
//do something
else if (somewhat_likely)
//do something
else if (highly_likely)
//do something
Run Code Online (Sandbox Code Playgroud)
很明显,排序版本会更快,但是为了便于阅读或存在副作用,我们可能希望对它们进行非最佳排序.在您实际运行代码之前,很难判断CPU在分支预测方面的表现如何.
因此,在尝试这个过程中,我最终回答了我自己的问题,但我还想听听其他意见/见解.
重要提示:此问题假定if语句可以任意重新排序,而不会对程序的行为产生任何其他影响.在我的回答中,三个条件测试是互斥的,不会产生副作用.当然,如果必须按某种顺序评估陈述以达到某些预期的行为,那么效率问题就没有实际意义.
由于第三方库的布局,我有类似下面的代码:
struct Base
{
static void SomeStaticMethod(){}
};
struct Derived1: private Base {};
struct Derived2: public Derived1 {
void SomeInstanceMethod(){
Base::SomeStaticMethod();
}
};
int main() {
Derived2 d2;
d2.SomeInstanceMethod();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我正在使用MSVC获得编译器错误C2247:
Base :: SomeStaticMethod无法访问,因为Derived1使用private从Base继承.
我知道我不能访问Base从成员Derived2通过继承,因为私人符,但我仍然应该能够调用静态方法Base-无论之间的继承关系Base和Derived2.
如何解决歧义并告诉编译器我只是调用静态方法?
这似乎是一个非常基本的问题,但我无法弄清楚.我有一个std::vectorDerived对象的原始指针,我只想使用赋值运算符将它复制到另一个Base指针向量.使用VC++我得到错误C2679"binary'=':没有找到操作符......"顺便说一下,我不想要对象的深层副本,我只是想复制指针.示例代码:
#include <vector>
using namespace std;
struct Base{};
struct Derived: public Base {};
int main (int argc, char* argv[])
{
vector<Derived*> V1;
vector<Base*> V2;
V2 = V1; //Compiler error here
return 0;
}
Run Code Online (Sandbox Code Playgroud)
让我感到困惑的是,我可以通过循环遍历它来复制矢量并使用push_back,如下所示:
for (Derived* p_derived : V1)
V2.push_back(p_derived);
Run Code Online (Sandbox Code Playgroud)
所以我的问题是,为什么作业失败,而push_back有效?对我来说似乎是一样的东西.
我经常使用普通的
if (Value * value = getValue())
{
// do something with value
}
else
{
// handle lack of value
}
Run Code Online (Sandbox Code Playgroud)
现在,我也经常这样做
QString error = someFunctionReturningAnErrorString(arg);
if (!error.isEmpty())
{
// handle the error
}
// empty error means: no error
Run Code Online (Sandbox Code Playgroud)
这一切都很好,但我希望error变量的范围是if-block.那有一个很好的习语吗?显然,我可以将整个部分包装在另一个块中.
显然,这不起作用:
if(QString error = someFunctionReturningAnErrorString(arg), !error.isEmpty())
{
// handle the error
}
// empty error means: no error
Run Code Online (Sandbox Code Playgroud)
不幸的是(但有充分的理由)QString无法转换为bool,所以这也不起作用:
if(QString error = someFunctionReturningAnErrorString(arg))
{
// handle the error
}
// empty error …Run Code Online (Sandbox Code Playgroud) 我有一个Container保存的对象,其类型可以从一些基类的任何组合衍生的(类TypeA,TypeB等).基类Container具有返回指向包含对象的指针的虚方法; nullptr如果包含的对象不是从期望的类派生的,那么它们应该返回.我想根据Container模板参数有选择地覆盖base的方法.我尝试使用SFINAE如下,但它不编译.我想避免专注Container于所有可能的组合,因为可能有很多.
#include <type_traits>
#include <iostream>
using namespace std;
class TypeA {};
class TypeB {};
class TypeAB: public TypeA, public TypeB {};
struct Container_base {
virtual TypeA* get_TypeA() {return nullptr;}
virtual TypeB* get_TypeB() {return nullptr;}
};
template <typename T>
struct Container: public Container_base
{
Container(): ptr(new T()) {}
//Override only if T is derived from TypeA
auto get_TypeA() -> enable_if<is_base_of<TypeA, T>::value, TypeA*>::type
{return ptr;}
//Override only if …Run Code Online (Sandbox Code Playgroud) 我有一个矢量:
std::vector<std::unique_ptr<int>>
Run Code Online (Sandbox Code Playgroud)
并希望unique_ptr<int>在指定位置插入几个新的.有成员函数,std::vector::insert(iterator position, size_type n, const value_type& val)但唉,复制的限制unique_ptr不允许使用这个重载.
我已经读过这个问题,但是那个插入unique_ptr已存在于另一个向量中的问题.我想创造新的.
我意识到我可以用循环来做,例如在向量的开头插入3个新项:
for (int n = 0; n != 3; ++n)
vec.insert(vec.begin(), std::make_unique<int>(0));
Run Code Online (Sandbox Code Playgroud)
但是我想知道是否有更简洁的方法来做到这一点,并且可能是一个预先分配新内存的方法.
编辑澄清:添加到向量的项目数是完全随意的 - 我在我的示例代码中写了3但它可以是任何值,而不一定是编译时已知的值.
我发现自己经常做这样的事情来连接从函数返回的几个向量(可能是类函数):
#include <vector>
#include <iostream>
using namespace std;
vector<int> v1;
const vector<int>& F1() {
cout << "F1 was called" << endl;
/*Populate v1, which may be an expensive operation*/
return v1;
}
int main() {
vector<int> Concat;
Concat.insert(Concat.end(), F1().begin(), F1().end());
/*Do something with Concat*/
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如我所料,F1()被调用两次,如果它是一个昂贵的函数调用,这可能是不可取的.另一种方法是将返回值复制F1()到一个临时向量中,该向量只需要一个函数调用,但是如果向量很大则会产生复制操作,这可能是不合需要的.我能想到的唯一另一种选择是创建一个指向临时向量的指针,并为其分配返回值,F1()如下所示:
int main() {
vector<int> Concat;
const vector<int>* temp = &F1();
Concat.insert(Concat.end(), temp->begin(), temp->end());
/*Do something with Concat*/
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这真的是最好的解决方案吗?使用临时变量似乎很麻烦,特别是如果我需要连接几个向量.我也觉得应该有一种方法来使用引用而不是指针来做到这一点.有什么建议?
我在子类QAbstractItemModel中显示a中的项目QTreeView,在这个子类(projectModel)中,我有一个函数来删除树视图中当前选择的索引. Component是用于表示模型的所有成员的类:
void
projectModel::deleteComponent()
{
QModelIndex child_index = _treeview->selectionModel()->currentIndex();
Component* child = static_cast<Component*>(child_index.internalPointer());
Component* parent = child->Parent();
QModelIndex parent_index = createIndex(parent->row(), 0, parent);
int row = child->row();
beginRemoveRows(parent_index, row, row);
parent->delete_child(child);
endRemoveRows();
}
Run Code Online (Sandbox Code Playgroud)
在呼叫之前,父母和孩子的指示和原始指针都很好beginRemoveRows; 调试器显示它们指向正确的项目及其父项.但是,程序在调用后崩溃了beginRemoveRows.具体来说,它崩溃了 projectModel::parent():
QModelIndex
projectModel::parent(const QModelIndex &index) const
{
if (!index.isValid())
return QModelIndex();
Component* item = getItem(index); //Fails to cast index internal pointer to a valid Component*
Component* parentItem = item->Parent();
if (parentItem == _rootnode) …Run Code Online (Sandbox Code Playgroud) 我发誓这不是任何看似无限数量的矢量连接线程的重复.对于我的情况,在派生类构造函数中,我需要将a传递std::vector<int>给基类构造函数,但传递的向量需要是另外两个向量的串联.例:
#include <vector>
using namespace std;
struct Base {
Base(vector<int> numbers) {
//Do something with numbers
}
};
struct Derived: public Base {
Derived(vector<int> numbers):
Base(concatenate(numbers, {4,5,6})) {} //Is there a built-in "concatenate" function?
};
int main (int argc, char* argv[])
{
Derived D({1,2,3});
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我显然可以通过编写自己的concatenate函数来实现这一点,但我想知道是否已经有了标准库方法来实现这一点.我发现的矢量级联的例子都不适合在初始化列表中使用,因为它们跨越多行; 我需要一个单线串联.
我惊讶地发现以下代码在MSVC下编译,运行和生成预期输出:
#include <iostream>
using namespace std;
struct Foo{
int _x;
Foo(int x): _x(x) {}
} //Note: no semi-colon after class definition.
//Makes this behave as a return type for the following function:
Foo_factory(int x)
{return Foo(x);}
int main (int argc, char* argv[])
{
Foo foo = Foo_factory(42);
cout << foo._x << endl; //Prints "42"
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我没有惊讶地看到MinGW无法编译错误"可能没有在返回类型中定义新类型".这只是该标准的另一个Microsoft例外,还是这个合法的C++?
我做了一个程序来评估这样做之间的性能差异:
func3(func2(func1()));
Run Code Online (Sandbox Code Playgroud)
对此:
retval1 = func1();
retval2 = func2(retval1);
func3(retval2);
Run Code Online (Sandbox Code Playgroud)
我更喜欢后者的可读性和易于调试,我想知道编译器(MSVC 12.0)是否会优化发布版本中的中间对象.我的测试程序是这样的:
#include <iostream>
using namespace std;
struct Indicator {
Indicator() {cout << "Default constructor" << endl;}
Indicator(const Indicator& other) {cout << "Copy constructor" << endl;}
const Indicator& operator=(const Indicator& other) {cout << "Assignment operator" << endl;}
~Indicator() {cout << "Destructor" << endl;}
};
Indicator func1()
{return Indicator();}
Indicator func2(Indicator&& i)
{return std::move(i);}
Indicator func3(Indicator&& i)
{return std::move(i);}
int main() {
Indicator i = func3(func2(func1()));
cout << &i << endl; …Run Code Online (Sandbox Code Playgroud) c++ ×11
vector ×3
inheritance ×2
optimization ×2
qt ×2
c++11 ×1
if-statement ×1
performance ×1
pointers ×1
qstring ×1
sfinae ×1
stdvector ×1
templates ×1
unique-ptr ×1
visual-c++ ×1