问题描述
我刚从format_int类的fmt库中发现了一些东西。它具有一个char缓冲区成员,以便您在调用类时在调用方法中在堆栈上分配堆栈空间。您可以从format_int返回一个char *,即使在类被销毁后它仍然有效。虽然std :: string也有一个c_str成员,该成员可以返回堆栈内存,但std :: string的析构函数会清除该内存,从而迫使用户在对象生存期内使用它。因此,相比之下,短暂的std :: string对象会迫使您在对象被破坏之前使用c_str的结果,而format_int则允许您将格式化的缓冲区用于该函数的其余部分。
c ++是否保证在函数结束之前不会重用堆栈,在调用函数的生存期内(超出format_int对象的生存期),是否可以安全地保留来自format_int类的缓冲区?这是我的编译器(MSVC)的怪癖吗?
ps。我认为保留内存是很偷偷摸摸的,我很好奇在现实世界中编译器是否会重用堆栈,或者该语言是否禁止这种行为。
解决方法
您可以从format_int返回一个char *,即使在类被破坏后,它仍然有效。
不是。当import com.google.android.material.bottomnavigation.BottomNavigationItemView;
import com.google.android.material.bottomnavigation.BottomNavigationMenuView;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.google.android.material.bottomnavigation.LabelVisibilityMode;
import android.annotation.SuppressLint;
import android.util.Log;
import java.lang.reflect.Field;
public class BottomNavigationViewHelper {
@SuppressLint("RestrictedApi")
public static void disableShiftMode(BottomNavigationView view) {
view.setLabelVisibilityMode(LabelVisibilityMode.LABEL_VISIBILITY_LABELED);
BottomNavigationMenuView menuView = (BottomNavigationMenuView) view.getChildAt(0);
try {
Field shiftingMode = menuView.getClass().getDeclaredField("mShiftingMode");
shiftingMode.setAccessible(true);
shiftingMode.setBoolean(menuView,false);
shiftingMode.setAccessible(false);
for (int i = 0; i < menuView.getChildCount(); i++) {
BottomNavigationItemView item = (BottomNavigationItemView) menuView.getChildAt(i);
//noinspection RestrictedApi
item.setShifting(false);
item.setLabelVisibilityMode( LabelVisibilityMode.LABEL_VISIBILITY_LABELED);
// set once again checked value,so view will be updated
//noinspection RestrictedApi
item.setChecked(item.getItemData().isChecked());
}
} catch (NoSuchFieldException e) {
Log.e("BNVHelper","Unable to get shift mode field",e);
} catch (IllegalAccessException e) {
Log.e("BNVHelper","Unable to change value of shift mode",e);
}
}
}
对象被销毁时,从import android.os.Bundle;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import androidx.appcompat.app.AppCompatActivity;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BottomNavigationView navView = findViewById(R.id.nav_view);
BottomNavigationViewHelper.disableShiftMode(navView);
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
R.id.navigation_settings,R.id.navigation_connection,R.id.navigation_status,R.id.navigation_report,R.id.navigation_profile
).build();
NavController navController = Navigation.findNavController(this,R.id.nav_host_fragment);
NavigationUI.setupActionBarWithNavController(this,navController,appBarConfiguration);
NavigationUI.setupWithNavController(navView,navController);
getSupportActionBar().hide();
}
}
返回的指针无效。这类似于std::basic_string::c_str
。
临时对象的堆栈空间是否可以重用?
它可以重复使用。